diff --git a/go.mod b/go.mod index e9a72dc61db..a13dfaffadf 100644 --- a/go.mod +++ b/go.mod @@ -1,17 +1,17 @@ module knative.dev/eventing -go 1.23.0 +go 1.23.8 require ( github.com/ahmetb/gen-crd-api-reference-docs v0.3.1-0.20210420163308-c1402a70e2f1 - github.com/cert-manager/cert-manager v1.16.3 + github.com/cert-manager/cert-manager v1.17.2 github.com/cloudevents/conformance v0.4.1 github.com/cloudevents/sdk-go/observability/opencensus/v2 v2.15.2 github.com/cloudevents/sdk-go/protocol/mqtt_paho/v2 v2.0.0-20240508060731-1ed9471c98bd - github.com/cloudevents/sdk-go/sql/v2 v2.0.0-20240712172937-3ce6b2f1f011 - github.com/cloudevents/sdk-go/v2 v2.15.2 - github.com/coreos/go-oidc/v3 v3.9.0 - github.com/eclipse/paho.golang v0.12.0 + github.com/cloudevents/sdk-go/sql/v2 v2.15.2 + github.com/cloudevents/sdk-go/v2 v2.16.0 + github.com/coreos/go-oidc/v3 v3.14.1 + github.com/eclipse/paho.golang v0.22.0 github.com/go-jose/go-jose/v3 v3.0.3 github.com/google/go-cmp v0.7.0 github.com/google/gofuzz v1.2.0 @@ -23,21 +23,21 @@ require ( github.com/kelseyhightower/envconfig v1.4.0 github.com/mitchellh/go-homedir v1.1.0 github.com/openzipkin/zipkin-go v0.4.3 - github.com/pelletier/go-toml/v2 v2.0.5 + github.com/pelletier/go-toml/v2 v2.2.4 github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/pkg/errors v0.9.1 - github.com/rickb777/date v1.13.0 + github.com/rickb777/date v1.21.1 github.com/robfig/cron/v3 v3.0.1 github.com/stretchr/testify v1.10.0 github.com/wavesoftware/go-ensure v1.0.0 go.opencensus.io v0.24.0 - go.opentelemetry.io/otel v1.34.0 - go.opentelemetry.io/otel/trace v1.34.0 - go.uber.org/atomic v1.10.0 + go.opentelemetry.io/otel v1.35.0 + go.opentelemetry.io/otel/trace v1.35.0 + go.uber.org/atomic v1.11.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 - golang.org/x/net v0.39.0 - golang.org/x/sync v0.13.0 + golang.org/x/net v0.40.0 + golang.org/x/sync v0.14.0 k8s.io/api v0.32.2 k8s.io/apiextensions-apiserver v0.32.1 k8s.io/apimachinery v0.32.2 @@ -65,6 +65,7 @@ require ( github.com/emicklei/go-restful/v3 v3.12.1 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/go-jose/go-jose/v4 v4.0.5 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect github.com/go-logr/logr v1.4.2 // indirect @@ -91,19 +92,19 @@ require ( github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/prometheus/statsd_exporter v0.22.7 // indirect - github.com/rickb777/plural v1.2.1 // indirect + github.com/rickb777/plural v1.4.2 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/spf13/cobra v1.8.1 // indirect github.com/spf13/pflag v1.0.6 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/x448/float16 v0.8.4 // indirect go.uber.org/automaxprocs v1.6.0 // indirect - golang.org/x/crypto v0.37.0 // indirect + golang.org/x/crypto v0.38.0 // indirect golang.org/x/mod v0.24.0 // indirect - golang.org/x/oauth2 v0.26.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/term v0.31.0 // indirect - golang.org/x/text v0.24.0 // indirect + golang.org/x/oauth2 v0.28.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/term v0.32.0 // indirect + golang.org/x/text v0.25.0 // indirect golang.org/x/time v0.10.0 // indirect golang.org/x/tools v0.32.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect diff --git a/go.sum b/go.sum index b19fa3e62c3..11b0dcfca4c 100644 --- a/go.sum +++ b/go.sum @@ -87,8 +87,8 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= -github.com/cert-manager/cert-manager v1.16.3 h1:seEF5eidFaeduaCuM85PFEuzH/1X/HOV5Y8zDQrHgpc= -github.com/cert-manager/cert-manager v1.16.3/go.mod h1:6JQ/GAZ6dH+erqS1BbaqorPy8idJzCtWFUmJQBTjo6Q= +github.com/cert-manager/cert-manager v1.17.2 h1:QQYTEOsHf/Z3BFzKH2sIILHJwZA5Ut0LYZlHyNViupg= +github.com/cert-manager/cert-manager v1.17.2/go.mod h1:2TmjsTQF8GZqc8fgLhXWCfbA6YwWCUHKxerJNbFh9eU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -106,10 +106,10 @@ github.com/cloudevents/sdk-go/observability/opencensus/v2 v2.15.2 h1:AbtPqiUDzKu github.com/cloudevents/sdk-go/observability/opencensus/v2 v2.15.2/go.mod h1:ZbYLE+yaEQ2j4vbRc9qzvGmg30A9LhwFt/1bSebNnbU= github.com/cloudevents/sdk-go/protocol/mqtt_paho/v2 v2.0.0-20240508060731-1ed9471c98bd h1:MGVlnkCz/b0vjfkM5tSVLD+4oaUnYuVEjiW6lAMJ9IM= github.com/cloudevents/sdk-go/protocol/mqtt_paho/v2 v2.0.0-20240508060731-1ed9471c98bd/go.mod h1:s+KZsVZst0bVW6vuKYb8CH49CcSJDO09+ZiIeKzJmqE= -github.com/cloudevents/sdk-go/sql/v2 v2.0.0-20240712172937-3ce6b2f1f011 h1:mx6avAROtrV9yTlBBH4Y8IAmspmcz9v44Pkcrjq0tAA= -github.com/cloudevents/sdk-go/sql/v2 v2.0.0-20240712172937-3ce6b2f1f011/go.mod h1:oqJ9+L9IXySYb8PN6M/g/K8y/WdVQunmmZhJnlLFcCk= -github.com/cloudevents/sdk-go/v2 v2.15.2 h1:54+I5xQEnI73RBhWHxbI1XJcqOFOVJN85vb41+8mHUc= -github.com/cloudevents/sdk-go/v2 v2.15.2/go.mod h1:lL7kSWAE/V8VI4Wh0jbL2v/jvqsm6tjmaQBSvxcv4uE= +github.com/cloudevents/sdk-go/sql/v2 v2.15.2 h1:TNaTeWIbDaci89xgXbmmNVGccawQOvEfWYLWrr7Fk/k= +github.com/cloudevents/sdk-go/sql/v2 v2.15.2/go.mod h1:us+PSk8OXdk8pDbRfvxy5w8ub5goKE7UP9PjKDY7TPw= +github.com/cloudevents/sdk-go/v2 v2.16.0 h1:wnunjgiLQCfYlyo+E4+mFlZtAh7pKn7vT8MMD3lSwCg= +github.com/cloudevents/sdk-go/v2 v2.16.0/go.mod h1:5YWqklyhDSmGzBK/JENKKXdulbPq0JFf3c/KEnMLqgg= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -120,8 +120,8 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/coreos/go-oidc/v3 v3.9.0 h1:0J/ogVOd4y8P0f0xUh8l9t07xRP/d8tccvjHl2dcsSo= -github.com/coreos/go-oidc/v3 v3.9.0/go.mod h1:rTKz2PYwftcrtoCzV5g5kvfJoWcm0Mk8AF8y1iAQro4= +github.com/coreos/go-oidc/v3 v3.14.1 h1:9ePWwfdwC4QKRlCXsJGou56adA/owXczOzwKdOumLqk= +github.com/coreos/go-oidc/v3 v3.14.1/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -133,8 +133,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc 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/eclipse/paho.golang v0.12.0 h1:EXQFJbJklDnUqW6lyAknMWRhM2NgpHxwrrL8riUmp3Q= -github.com/eclipse/paho.golang v0.12.0/go.mod h1:TSDCUivu9JnoR9Hl+H7sQMcHkejWH2/xKK1NJGtLbIE= +github.com/eclipse/paho.golang v0.22.0 h1:JhhUngr8TBlyUZDZw/L6WVayPi9qmSmdWeki48i5AVE= +github.com/eclipse/paho.golang v0.22.0/go.mod h1:9ZiYJ93iEfGRJri8tErNeStPKLXIGBHiqbHV74t5pqI= github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= @@ -168,6 +168,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= +github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= +github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -399,7 +401,6 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= @@ -422,16 +423,12 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= 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.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M= github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= @@ -440,8 +437,8 @@ github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LD github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= -github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc= github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= @@ -495,10 +492,10 @@ github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoG github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rickb777/date v1.13.0 h1:+8AmwLuY1d/rldzdqvqTEg7107bZ8clW37x4nsdG3Hs= -github.com/rickb777/date v1.13.0/go.mod h1:GZf3LoGnxPWjX+/1TXOuzHefZFDovTyNLHDMd3qH70k= -github.com/rickb777/plural v1.2.1 h1:UitRAgR70+yHFt26Tmj/F9dU9aV6UfjGXSbO1DcC9/U= -github.com/rickb777/plural v1.2.1/go.mod h1:j058+3M5QQFgcZZ2oKIOekcygoZUL8gKW5yRO14BuAw= +github.com/rickb777/date v1.21.1 h1:tUcQS8riIRoYK5kUAv5aevllFEYUEk2x8OYDyoldOn4= +github.com/rickb777/date v1.21.1/go.mod h1:gnDexsbXViZr2fCKMrY3m6IfAF5U2vSkEaiGJcNFaLQ= +github.com/rickb777/plural v1.4.2 h1:Kl/syFGLFZ5EbuV8c9SVud8s5HI2HpCCtOMw2U1kS+A= +github.com/rickb777/plural v1.4.2/go.mod h1:kdmXUpmKBJTS0FtG/TFumd//VBWsNTD7zOw7x4umxNw= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -527,7 +524,6 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= -github.com/sqs/goreturns v0.0.0-20181028201513-538ac6014518/go.mod h1:CKI4AZ4XmGV240rTHfO0hfE83S6/a3/Q1siZJ/vXf7A= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -573,21 +569,21 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= -go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= -go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= -go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= +go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= +go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= +go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= -go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= -go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= +go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -612,8 +608,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -682,7 +678,6 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -704,8 +699,8 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -724,8 +719,8 @@ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE= -golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= +golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -740,8 +735,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -758,13 +753,11 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -823,15 +816,15 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= -golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -844,8 +837,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -887,7 +880,6 @@ golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512001501-aaeff5de670a/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= diff --git a/vendor/github.com/cert-manager/cert-manager/LICENSES b/vendor/github.com/cert-manager/cert-manager/LICENSES index 0c644fe5a34..baf80451dc8 100644 --- a/vendor/github.com/cert-manager/cert-manager/LICENSES +++ b/vendor/github.com/cert-manager/cert-manager/LICENSES @@ -1,6 +1,7 @@ +cel.dev/expr,https://github.com/google/cel-spec/blob/v0.19.1/LICENSE,Apache-2.0 cloud.google.com/go/auth,https://github.com/googleapis/google-cloud-go/blob/auth/v0.9.4/auth/LICENSE,Apache-2.0 cloud.google.com/go/auth/oauth2adapt,https://github.com/googleapis/google-cloud-go/blob/auth/oauth2adapt/v0.2.4/auth/oauth2adapt/LICENSE,Apache-2.0 -cloud.google.com/go/compute/metadata,https://github.com/googleapis/google-cloud-go/blob/compute/metadata/v0.5.1/compute/metadata/LICENSE,Apache-2.0 +cloud.google.com/go/compute/metadata,https://github.com/googleapis/google-cloud-go/blob/compute/metadata/v0.5.2/compute/metadata/LICENSE,Apache-2.0 github.com/Azure/azure-sdk-for-go/sdk/azcore,https://github.com/Azure/azure-sdk-for-go/blob/sdk/azcore/v1.14.0/sdk/azcore/LICENSE.txt,MIT github.com/Azure/azure-sdk-for-go/sdk/azidentity,https://github.com/Azure/azure-sdk-for-go/blob/sdk/azidentity/v1.7.0/sdk/azidentity/LICENSE.txt,MIT github.com/Azure/azure-sdk-for-go/sdk/internal,https://github.com/Azure/azure-sdk-for-go/blob/sdk/internal/v1.10.0/sdk/internal/LICENSE.txt,MIT @@ -9,9 +10,9 @@ github.com/Azure/go-ntlmssp,https://github.com/Azure/go-ntlmssp/blob/754e6932135 github.com/AzureAD/microsoft-authentication-library-for-go/apps,https://github.com/AzureAD/microsoft-authentication-library-for-go/blob/v1.2.2/LICENSE,MIT github.com/Khan/genqlient/graphql,https://github.com/Khan/genqlient/blob/v0.7.0/LICENSE,MIT github.com/NYTimes/gziphandler,https://github.com/NYTimes/gziphandler/blob/v1.1.1/LICENSE,Apache-2.0 -github.com/Venafi/vcert/v5,https://github.com/Venafi/vcert/blob/v5.7.1/LICENSE,Apache-2.0 +github.com/Venafi/vcert/v5,https://github.com/Venafi/vcert/blob/v5.8.0/LICENSE,Apache-2.0 github.com/akamai/AkamaiOPEN-edgegrid-golang,https://github.com/akamai/AkamaiOPEN-edgegrid-golang/blob/v1.2.2/LICENSE,Apache-2.0 -github.com/antlr4-go/antlr/v4,https://github.com/antlr4-go/antlr/blob/v4.13.0/LICENSE,BSD-3-Clause +github.com/antlr4-go/antlr/v4,https://github.com/antlr4-go/antlr/blob/v4.13.1/LICENSE,BSD-3-Clause github.com/asaskevich/govalidator,https://github.com/asaskevich/govalidator/blob/a9d515a09cc2/LICENSE,MIT github.com/aws/aws-sdk-go-v2,https://github.com/aws/aws-sdk-go-v2/blob/v1.31.0/LICENSE.txt,Apache-2.0 github.com/aws/aws-sdk-go-v2/config,https://github.com/aws/aws-sdk-go-v2/blob/config/v1.27.36/config/LICENSE.txt,Apache-2.0 @@ -48,12 +49,12 @@ github.com/digitalocean/godo,https://github.com/digitalocean/godo/blob/v1.125.0/ github.com/emicklei/go-restful/v3,https://github.com/emicklei/go-restful/blob/v3.12.1/LICENSE,MIT github.com/evanphx/json-patch/v5,https://github.com/evanphx/json-patch/blob/v5.9.0/v5/LICENSE,BSD-3-Clause github.com/felixge/httpsnoop,https://github.com/felixge/httpsnoop/blob/v1.0.4/LICENSE.txt,MIT -github.com/fsnotify/fsnotify,https://github.com/fsnotify/fsnotify/blob/v1.7.0/LICENSE,BSD-3-Clause +github.com/fsnotify/fsnotify,https://github.com/fsnotify/fsnotify/blob/v1.8.0/LICENSE,BSD-3-Clause github.com/fxamacker/cbor/v2,https://github.com/fxamacker/cbor/blob/v2.7.0/LICENSE,MIT github.com/go-asn1-ber/asn1-ber,https://github.com/go-asn1-ber/asn1-ber/blob/v1.5.6/LICENSE,MIT github.com/go-http-utils/headers,https://github.com/go-http-utils/headers/blob/fed159eddc2a/LICENSE,MIT -github.com/go-jose/go-jose/v4,https://github.com/go-jose/go-jose/blob/v4.0.2/LICENSE,Apache-2.0 -github.com/go-jose/go-jose/v4/json,https://github.com/go-jose/go-jose/blob/v4.0.2/json/LICENSE,BSD-3-Clause +github.com/go-jose/go-jose/v4,https://github.com/go-jose/go-jose/blob/v4.0.5/LICENSE,Apache-2.0 +github.com/go-jose/go-jose/v4/json,https://github.com/go-jose/go-jose/blob/v4.0.5/json/LICENSE,BSD-3-Clause github.com/go-ldap/ldap/v3,https://github.com/go-ldap/ldap/blob/v3.4.8/v3/LICENSE,MIT github.com/go-logr/logr,https://github.com/go-logr/logr/blob/v1.4.2/LICENSE,Apache-2.0 github.com/go-logr/stdr,https://github.com/go-logr/stdr/blob/v1.2.2/LICENSE,Apache-2.0 @@ -62,13 +63,14 @@ github.com/go-openapi/jsonpointer,https://github.com/go-openapi/jsonpointer/blob github.com/go-openapi/jsonreference,https://github.com/go-openapi/jsonreference/blob/v0.21.0/LICENSE,Apache-2.0 github.com/go-openapi/swag,https://github.com/go-openapi/swag/blob/v0.23.0/LICENSE,Apache-2.0 github.com/gogo/protobuf,https://github.com/gogo/protobuf/blob/v1.3.2/LICENSE,BSD-3-Clause -github.com/golang-jwt/jwt/v5,https://github.com/golang-jwt/jwt/blob/v5.2.1/LICENSE,MIT +github.com/golang-jwt/jwt/v5,https://github.com/golang-jwt/jwt/blob/v5.2.2/LICENSE,MIT github.com/golang/groupcache/lru,https://github.com/golang/groupcache/blob/41bb18bfe9da/LICENSE,Apache-2.0 -github.com/golang/protobuf,https://github.com/golang/protobuf/blob/v1.5.4/LICENSE,BSD-3-Clause +github.com/golang/protobuf/proto,https://github.com/golang/protobuf/blob/v1.5.4/LICENSE,BSD-3-Clause github.com/golang/snappy,https://github.com/golang/snappy/blob/v0.0.4/LICENSE,BSD-3-Clause -github.com/google/cel-go,https://github.com/google/cel-go/blob/v0.20.1/LICENSE,Apache-2.0 -github.com/google/cel-go,https://github.com/google/cel-go/blob/v0.20.1/LICENSE,BSD-3-Clause -github.com/google/gnostic-models,https://github.com/google/gnostic-models/blob/v0.6.8/LICENSE,Apache-2.0 +github.com/google/btree,https://github.com/google/btree/blob/v1.1.3/LICENSE,Apache-2.0 +github.com/google/cel-go,https://github.com/google/cel-go/blob/v0.22.1/LICENSE,Apache-2.0 +github.com/google/cel-go,https://github.com/google/cel-go/blob/v0.22.1/LICENSE,BSD-3-Clause +github.com/google/gnostic-models,https://github.com/google/gnostic-models/blob/v0.6.9/LICENSE,Apache-2.0 github.com/google/go-cmp/cmp,https://github.com/google/go-cmp/blob/v0.6.0/LICENSE,BSD-3-Clause github.com/google/go-querystring/query,https://github.com/google/go-querystring/blob/v1.1.0/LICENSE,BSD-3-Clause github.com/google/gofuzz,https://github.com/google/gofuzz/blob/v1.2.0/LICENSE,Apache-2.0 @@ -76,9 +78,9 @@ github.com/google/s2a-go,https://github.com/google/s2a-go/blob/v0.1.8/LICENSE.md github.com/google/uuid,https://github.com/google/uuid/blob/v1.6.0/LICENSE,BSD-3-Clause github.com/googleapis/enterprise-certificate-proxy/client,https://github.com/googleapis/enterprise-certificate-proxy/blob/v0.3.4/LICENSE,Apache-2.0 github.com/googleapis/gax-go/v2,https://github.com/googleapis/gax-go/blob/v2.13.0/v2/LICENSE,BSD-3-Clause -github.com/gorilla/websocket,https://github.com/gorilla/websocket/blob/v1.5.1/LICENSE,BSD-3-Clause +github.com/gorilla/websocket,https://github.com/gorilla/websocket/blob/v1.5.3/LICENSE,BSD-2-Clause github.com/grpc-ecosystem/go-grpc-prometheus,https://github.com/grpc-ecosystem/go-grpc-prometheus/blob/v1.2.0/LICENSE,Apache-2.0 -github.com/grpc-ecosystem/grpc-gateway/v2,https://github.com/grpc-ecosystem/grpc-gateway/blob/v2.20.0/LICENSE,BSD-3-Clause +github.com/grpc-ecosystem/grpc-gateway/v2,https://github.com/grpc-ecosystem/grpc-gateway/blob/v2.25.1/LICENSE,BSD-3-Clause github.com/hashicorp/errwrap,https://github.com/hashicorp/errwrap/blob/v1.1.0/LICENSE,MPL-2.0 github.com/hashicorp/go-cleanhttp,https://github.com/hashicorp/go-cleanhttp/blob/v0.5.2/LICENSE,MPL-2.0 github.com/hashicorp/go-multierror,https://github.com/hashicorp/go-multierror/blob/v1.1.1/LICENSE,MPL-2.0 @@ -90,19 +92,18 @@ github.com/hashicorp/go-sockaddr,https://github.com/hashicorp/go-sockaddr/blob/v github.com/hashicorp/hcl,https://github.com/hashicorp/hcl/blob/v1.0.1-vault-5/LICENSE,MPL-2.0 github.com/hashicorp/vault/api,https://github.com/hashicorp/vault/blob/api/v1.15.0/api/LICENSE,MPL-2.0 github.com/hashicorp/vault/sdk/helper,https://github.com/hashicorp/vault/blob/sdk/v0.14.0/sdk/LICENSE,MPL-2.0 -github.com/imdario/mergo,https://github.com/imdario/mergo/blob/v0.3.16/LICENSE,BSD-3-Clause github.com/jmespath/go-jmespath,https://github.com/jmespath/go-jmespath/blob/b0104c826a24/LICENSE,Apache-2.0 github.com/josharian/intern,https://github.com/josharian/intern/blob/v1.0.0/license.md,MIT github.com/json-iterator/go,https://github.com/json-iterator/go/blob/v1.1.12/LICENSE,MIT -github.com/klauspost/compress,https://github.com/klauspost/compress/blob/v1.17.9/LICENSE,MIT -github.com/klauspost/compress,https://github.com/klauspost/compress/blob/v1.17.9/LICENSE,Apache-2.0 -github.com/klauspost/compress,https://github.com/klauspost/compress/blob/v1.17.9/LICENSE,BSD-3-Clause -github.com/klauspost/compress/internal/snapref,https://github.com/klauspost/compress/blob/v1.17.9/internal/snapref/LICENSE,BSD-3-Clause -github.com/klauspost/compress/zstd/internal/xxhash,https://github.com/klauspost/compress/blob/v1.17.9/zstd/internal/xxhash/LICENSE.txt,MIT +github.com/klauspost/compress,https://github.com/klauspost/compress/blob/v1.17.11/LICENSE,MIT +github.com/klauspost/compress,https://github.com/klauspost/compress/blob/v1.17.11/LICENSE,Apache-2.0 +github.com/klauspost/compress,https://github.com/klauspost/compress/blob/v1.17.11/LICENSE,BSD-3-Clause +github.com/klauspost/compress/internal/snapref,https://github.com/klauspost/compress/blob/v1.17.11/internal/snapref/LICENSE,BSD-3-Clause +github.com/klauspost/compress/zstd/internal/xxhash,https://github.com/klauspost/compress/blob/v1.17.11/zstd/internal/xxhash/LICENSE.txt,MIT github.com/kr/pretty,https://github.com/kr/pretty/blob/v0.3.1/License,MIT github.com/kr/text,https://github.com/kr/text/blob/v0.2.0/License,MIT github.com/kylelemons/godebug,https://github.com/kylelemons/godebug/blob/v1.1.0/LICENSE,Apache-2.0 -github.com/mailru/easyjson,https://github.com/mailru/easyjson/blob/v0.7.7/LICENSE,MIT +github.com/mailru/easyjson,https://github.com/mailru/easyjson/blob/v0.9.0/LICENSE,MIT github.com/miekg/dns,https://github.com/miekg/dns/blob/v1.1.62/LICENSE,BSD-3-Clause github.com/mitchellh/go-homedir,https://github.com/mitchellh/go-homedir/blob/v1.1.0/LICENSE,MIT github.com/mitchellh/mapstructure,https://github.com/mitchellh/mapstructure/blob/v1.5.0/LICENSE,MIT @@ -114,12 +115,12 @@ github.com/pavlo-v-chernykh/keystore-go/v4,https://github.com/pavlo-v-chernykh/k github.com/pierrec/lz4,https://github.com/pierrec/lz4/blob/v2.6.1/LICENSE,BSD-3-Clause github.com/pkg/browser,https://github.com/pkg/browser/blob/5ac0b6a4141c/LICENSE,BSD-2-Clause github.com/pkg/errors,https://github.com/pkg/errors/blob/v0.9.1/LICENSE,BSD-2-Clause -github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil,https://github.com/prometheus/client_golang/blob/v1.20.4/internal/github.com/golang/gddo/LICENSE,BSD-3-Clause -github.com/prometheus/client_golang/prometheus,https://github.com/prometheus/client_golang/blob/v1.20.4/LICENSE,Apache-2.0 +github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil,https://github.com/prometheus/client_golang/blob/v1.20.5/internal/github.com/golang/gddo/LICENSE,BSD-3-Clause +github.com/prometheus/client_golang/prometheus,https://github.com/prometheus/client_golang/blob/v1.20.5/LICENSE,Apache-2.0 github.com/prometheus/client_model/go,https://github.com/prometheus/client_model/blob/v0.6.1/LICENSE,Apache-2.0 -github.com/prometheus/common,https://github.com/prometheus/common/blob/v0.55.0/LICENSE,Apache-2.0 +github.com/prometheus/common,https://github.com/prometheus/common/blob/v0.61.0/LICENSE,Apache-2.0 github.com/prometheus/procfs,https://github.com/prometheus/procfs/blob/v0.15.1/LICENSE,Apache-2.0 -github.com/rogpeppe/go-internal/fmtsort,https://github.com/rogpeppe/go-internal/blob/v1.12.0/LICENSE,BSD-3-Clause +github.com/rogpeppe/go-internal/fmtsort,https://github.com/rogpeppe/go-internal/blob/v1.13.1/LICENSE,BSD-3-Clause github.com/ryanuber/go-glob,https://github.com/ryanuber/go-glob/blob/v1.0.0/LICENSE,MIT github.com/sirupsen/logrus,https://github.com/sirupsen/logrus/blob/v1.9.3/LICENSE,MIT github.com/sosodev/duration,https://github.com/sosodev/duration/blob/v1.3.1/LICENSE,MIT @@ -129,66 +130,68 @@ github.com/stoewer/go-strcase,https://github.com/stoewer/go-strcase/blob/v1.3.0/ github.com/vektah/gqlparser/v2,https://github.com/vektah/gqlparser/blob/v2.5.15/LICENSE,MIT github.com/x448/float16,https://github.com/x448/float16/blob/v0.8.4/LICENSE,MIT github.com/youmark/pkcs8,https://github.com/youmark/pkcs8/blob/3c2c7870ae76/LICENSE,MIT -go.etcd.io/etcd/api/v3,https://github.com/etcd-io/etcd/blob/api/v3.5.14/api/LICENSE,Apache-2.0 -go.etcd.io/etcd/client/pkg/v3,https://github.com/etcd-io/etcd/blob/client/pkg/v3.5.14/client/pkg/LICENSE,Apache-2.0 -go.etcd.io/etcd/client/v3,https://github.com/etcd-io/etcd/blob/client/v3.5.14/client/v3/LICENSE,Apache-2.0 +go.etcd.io/etcd/api/v3,https://github.com/etcd-io/etcd/blob/api/v3.5.17/api/LICENSE,Apache-2.0 +go.etcd.io/etcd/client/pkg/v3,https://github.com/etcd-io/etcd/blob/client/pkg/v3.5.17/client/pkg/LICENSE,Apache-2.0 +go.etcd.io/etcd/client/v3,https://github.com/etcd-io/etcd/blob/client/v3.5.17/client/v3/LICENSE,Apache-2.0 go.opencensus.io,https://github.com/census-instrumentation/opencensus-go/blob/v0.24.0/LICENSE,Apache-2.0 -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc,https://github.com/open-telemetry/opentelemetry-go-contrib/blob/instrumentation/google.golang.org/grpc/otelgrpc/v0.54.0/instrumentation/google.golang.org/grpc/otelgrpc/LICENSE,Apache-2.0 -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp,https://github.com/open-telemetry/opentelemetry-go-contrib/blob/instrumentation/net/http/otelhttp/v0.54.0/instrumentation/net/http/otelhttp/LICENSE,Apache-2.0 -go.opentelemetry.io/otel,https://github.com/open-telemetry/opentelemetry-go/blob/v1.29.0/LICENSE,Apache-2.0 -go.opentelemetry.io/otel/exporters/otlp/otlptrace,https://github.com/open-telemetry/opentelemetry-go/blob/exporters/otlp/otlptrace/v1.28.0/exporters/otlp/otlptrace/LICENSE,Apache-2.0 -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc,https://github.com/open-telemetry/opentelemetry-go/blob/exporters/otlp/otlptrace/otlptracegrpc/v1.27.0/exporters/otlp/otlptrace/otlptracegrpc/LICENSE,Apache-2.0 -go.opentelemetry.io/otel/metric,https://github.com/open-telemetry/opentelemetry-go/blob/metric/v1.29.0/metric/LICENSE,Apache-2.0 -go.opentelemetry.io/otel/sdk,https://github.com/open-telemetry/opentelemetry-go/blob/sdk/v1.28.0/sdk/LICENSE,Apache-2.0 -go.opentelemetry.io/otel/trace,https://github.com/open-telemetry/opentelemetry-go/blob/trace/v1.29.0/trace/LICENSE,Apache-2.0 -go.opentelemetry.io/proto/otlp,https://github.com/open-telemetry/opentelemetry-proto-go/blob/otlp/v1.3.1/otlp/LICENSE,Apache-2.0 +go.opentelemetry.io/auto/sdk,https://github.com/open-telemetry/opentelemetry-go-instrumentation/blob/sdk/v1.1.0/sdk/LICENSE,Apache-2.0 +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc,https://github.com/open-telemetry/opentelemetry-go-contrib/blob/instrumentation/google.golang.org/grpc/otelgrpc/v0.58.0/instrumentation/google.golang.org/grpc/otelgrpc/LICENSE,Apache-2.0 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp,https://github.com/open-telemetry/opentelemetry-go-contrib/blob/instrumentation/net/http/otelhttp/v0.58.0/instrumentation/net/http/otelhttp/LICENSE,Apache-2.0 +go.opentelemetry.io/otel,https://github.com/open-telemetry/opentelemetry-go/blob/v1.33.0/LICENSE,Apache-2.0 +go.opentelemetry.io/otel/exporters/otlp/otlptrace,https://github.com/open-telemetry/opentelemetry-go/blob/exporters/otlp/otlptrace/v1.33.0/exporters/otlp/otlptrace/LICENSE,Apache-2.0 +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc,https://github.com/open-telemetry/opentelemetry-go/blob/exporters/otlp/otlptrace/otlptracegrpc/v1.33.0/exporters/otlp/otlptrace/otlptracegrpc/LICENSE,Apache-2.0 +go.opentelemetry.io/otel/metric,https://github.com/open-telemetry/opentelemetry-go/blob/metric/v1.33.0/metric/LICENSE,Apache-2.0 +go.opentelemetry.io/otel/sdk,https://github.com/open-telemetry/opentelemetry-go/blob/sdk/v1.33.0/sdk/LICENSE,Apache-2.0 +go.opentelemetry.io/otel/trace,https://github.com/open-telemetry/opentelemetry-go/blob/trace/v1.33.0/trace/LICENSE,Apache-2.0 +go.opentelemetry.io/proto/otlp,https://github.com/open-telemetry/opentelemetry-proto-go/blob/otlp/v1.4.0/otlp/LICENSE,Apache-2.0 go.uber.org/multierr,https://github.com/uber-go/multierr/blob/v1.11.0/LICENSE.txt,MIT go.uber.org/zap,https://github.com/uber-go/zap/blob/v1.27.0/LICENSE,MIT -golang.org/x/crypto,https://cs.opensource.google/go/x/crypto/+/v0.31.0:LICENSE,BSD-3-Clause -golang.org/x/exp,https://cs.opensource.google/go/x/exp/+/8a7402ab:LICENSE,BSD-3-Clause -golang.org/x/net,https://cs.opensource.google/go/x/net/+/v0.33.0:LICENSE,BSD-3-Clause -golang.org/x/oauth2,https://cs.opensource.google/go/x/oauth2/+/v0.23.0:LICENSE,BSD-3-Clause -golang.org/x/sync,https://cs.opensource.google/go/x/sync/+/v0.10.0:LICENSE,BSD-3-Clause -golang.org/x/sys,https://cs.opensource.google/go/x/sys/+/v0.28.0:LICENSE,BSD-3-Clause -golang.org/x/term,https://cs.opensource.google/go/x/term/+/v0.27.0:LICENSE,BSD-3-Clause -golang.org/x/text,https://cs.opensource.google/go/x/text/+/v0.21.0:LICENSE,BSD-3-Clause -golang.org/x/time/rate,https://cs.opensource.google/go/x/time/+/v0.6.0:LICENSE,BSD-3-Clause +golang.org/x/crypto,https://cs.opensource.google/go/x/crypto/+/v0.36.0:LICENSE,BSD-3-Clause +golang.org/x/exp,https://cs.opensource.google/go/x/exp/+/b2144cdd:LICENSE,BSD-3-Clause +golang.org/x/net,https://cs.opensource.google/go/x/net/+/v0.38.0:LICENSE,BSD-3-Clause +golang.org/x/oauth2,https://cs.opensource.google/go/x/oauth2/+/v0.28.0:LICENSE,BSD-3-Clause +golang.org/x/sync,https://cs.opensource.google/go/x/sync/+/v0.12.0:LICENSE,BSD-3-Clause +golang.org/x/sys,https://cs.opensource.google/go/x/sys/+/v0.31.0:LICENSE,BSD-3-Clause +golang.org/x/term,https://cs.opensource.google/go/x/term/+/v0.30.0:LICENSE,BSD-3-Clause +golang.org/x/text,https://cs.opensource.google/go/x/text/+/v0.23.0:LICENSE,BSD-3-Clause +golang.org/x/time/rate,https://cs.opensource.google/go/x/time/+/v0.8.0:LICENSE,BSD-3-Clause gomodules.xyz/jsonpatch/v2,https://github.com/gomodules/jsonpatch/blob/v2.4.0/v2/LICENSE,Apache-2.0 google.golang.org/api,https://github.com/googleapis/google-api-go-client/blob/v0.198.0/LICENSE,BSD-3-Clause google.golang.org/api/internal/third_party/uritemplates,https://github.com/googleapis/google-api-go-client/blob/v0.198.0/internal/third_party/uritemplates/LICENSE,BSD-3-Clause -google.golang.org/genproto/googleapis/api,https://github.com/googleapis/go-genproto/blob/7e3bb234dfed/googleapis/api/LICENSE,Apache-2.0 -google.golang.org/genproto/googleapis/rpc,https://github.com/googleapis/go-genproto/blob/8af14fe29dc1/googleapis/rpc/LICENSE,Apache-2.0 -google.golang.org/grpc,https://github.com/grpc/grpc-go/blob/v1.66.2/LICENSE,Apache-2.0 -google.golang.org/protobuf,https://github.com/protocolbuffers/protobuf-go/blob/v1.34.2/LICENSE,BSD-3-Clause +google.golang.org/genproto/googleapis/api,https://github.com/googleapis/go-genproto/blob/6b3ec007d9bb/googleapis/api/LICENSE,Apache-2.0 +google.golang.org/genproto/googleapis/rpc,https://github.com/googleapis/go-genproto/blob/6b3ec007d9bb/googleapis/rpc/LICENSE,Apache-2.0 +google.golang.org/grpc,https://github.com/grpc/grpc-go/blob/v1.69.2/LICENSE,Apache-2.0 +google.golang.org/protobuf,https://github.com/protocolbuffers/protobuf-go/blob/v1.36.0/LICENSE,BSD-3-Clause gopkg.in/evanphx/json-patch.v4,https://github.com/evanphx/json-patch/blob/v4.12.0/LICENSE,BSD-3-Clause gopkg.in/inf.v0,https://github.com/go-inf/inf/blob/v0.9.1/LICENSE,BSD-3-Clause gopkg.in/ini.v1,https://github.com/go-ini/ini/blob/v1.67.0/LICENSE,Apache-2.0 gopkg.in/natefinch/lumberjack.v2,https://github.com/natefinch/lumberjack/blob/v2.2.1/LICENSE,MIT gopkg.in/yaml.v2,https://github.com/go-yaml/yaml/blob/v2.4.0/LICENSE,Apache-2.0 gopkg.in/yaml.v3,https://github.com/go-yaml/yaml/blob/v3.0.1/LICENSE,MIT -k8s.io/api,https://github.com/kubernetes/api/blob/v0.31.1/LICENSE,Apache-2.0 -k8s.io/apiextensions-apiserver/pkg,https://github.com/kubernetes/apiextensions-apiserver/blob/v0.31.1/LICENSE,Apache-2.0 -k8s.io/apimachinery/pkg,https://github.com/kubernetes/apimachinery/blob/v0.31.1/LICENSE,Apache-2.0 -k8s.io/apimachinery/third_party/forked/golang,https://github.com/kubernetes/apimachinery/blob/v0.31.1/third_party/forked/golang/LICENSE,BSD-3-Clause -k8s.io/apiserver,https://github.com/kubernetes/apiserver/blob/v0.31.1/LICENSE,Apache-2.0 -k8s.io/client-go,https://github.com/kubernetes/client-go/blob/v0.31.1/LICENSE,Apache-2.0 -k8s.io/component-base,https://github.com/kubernetes/component-base/blob/v0.31.1/LICENSE,Apache-2.0 +k8s.io/api,https://github.com/kubernetes/api/blob/v0.32.0/LICENSE,Apache-2.0 +k8s.io/apiextensions-apiserver/pkg,https://github.com/kubernetes/apiextensions-apiserver/blob/v0.32.0/LICENSE,Apache-2.0 +k8s.io/apimachinery/pkg,https://github.com/kubernetes/apimachinery/blob/v0.32.0/LICENSE,Apache-2.0 +k8s.io/apimachinery/third_party/forked/golang,https://github.com/kubernetes/apimachinery/blob/v0.32.0/third_party/forked/golang/LICENSE,BSD-3-Clause +k8s.io/apiserver,https://github.com/kubernetes/apiserver/blob/v0.32.0/LICENSE,Apache-2.0 +k8s.io/client-go,https://github.com/kubernetes/client-go/blob/v0.32.0/LICENSE,Apache-2.0 +k8s.io/component-base,https://github.com/kubernetes/component-base/blob/v0.32.0/LICENSE,Apache-2.0 k8s.io/klog/v2,https://github.com/kubernetes/klog/blob/v2.130.1/LICENSE,Apache-2.0 -k8s.io/kms,https://github.com/kubernetes/kms/blob/v0.31.1/LICENSE,Apache-2.0 +k8s.io/kms,https://github.com/kubernetes/kms/blob/v0.32.0/LICENSE,Apache-2.0 k8s.io/kube-aggregator/pkg/apis/apiregistration,https://github.com/kubernetes/kube-aggregator/blob/v0.31.1/LICENSE,Apache-2.0 -k8s.io/kube-openapi/pkg,https://github.com/kubernetes/kube-openapi/blob/9e1beecbcb38/LICENSE,Apache-2.0 -k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json,https://github.com/kubernetes/kube-openapi/blob/9e1beecbcb38/pkg/internal/third_party/go-json-experiment/json/LICENSE,BSD-3-Clause -k8s.io/kube-openapi/pkg/validation/errors,https://github.com/kubernetes/kube-openapi/blob/9e1beecbcb38/pkg/validation/errors/LICENSE,Apache-2.0 -k8s.io/kube-openapi/pkg/validation/spec,https://github.com/kubernetes/kube-openapi/blob/9e1beecbcb38/pkg/validation/spec/LICENSE,Apache-2.0 -k8s.io/kube-openapi/pkg/validation/strfmt,https://github.com/kubernetes/kube-openapi/blob/9e1beecbcb38/pkg/validation/strfmt/LICENSE,Apache-2.0 -k8s.io/utils,https://github.com/kubernetes/utils/blob/49e7df575cb6/LICENSE,Apache-2.0 -k8s.io/utils/internal/third_party/forked/golang,https://github.com/kubernetes/utils/blob/49e7df575cb6/internal/third_party/forked/golang/LICENSE,BSD-3-Clause -sigs.k8s.io/apiserver-network-proxy/konnectivity-client,https://github.com/kubernetes-sigs/apiserver-network-proxy/blob/konnectivity-client/v0.30.3/konnectivity-client/LICENSE,Apache-2.0 +k8s.io/kube-openapi/pkg,https://github.com/kubernetes/kube-openapi/blob/2c72e554b1e7/LICENSE,Apache-2.0 +k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json,https://github.com/kubernetes/kube-openapi/blob/2c72e554b1e7/pkg/internal/third_party/go-json-experiment/json/LICENSE,BSD-3-Clause +k8s.io/kube-openapi/pkg/internal/third_party/govalidator,https://github.com/kubernetes/kube-openapi/blob/2c72e554b1e7/pkg/internal/third_party/govalidator/LICENSE,MIT +k8s.io/kube-openapi/pkg/validation/errors,https://github.com/kubernetes/kube-openapi/blob/2c72e554b1e7/pkg/validation/errors/LICENSE,Apache-2.0 +k8s.io/kube-openapi/pkg/validation/spec,https://github.com/kubernetes/kube-openapi/blob/2c72e554b1e7/pkg/validation/spec/LICENSE,Apache-2.0 +k8s.io/kube-openapi/pkg/validation/strfmt,https://github.com/kubernetes/kube-openapi/blob/2c72e554b1e7/pkg/validation/strfmt/LICENSE,Apache-2.0 +k8s.io/utils,https://github.com/kubernetes/utils/blob/24370beab758/LICENSE,Apache-2.0 +k8s.io/utils/internal/third_party/forked/golang,https://github.com/kubernetes/utils/blob/24370beab758/internal/third_party/forked/golang/LICENSE,BSD-3-Clause +sigs.k8s.io/apiserver-network-proxy/konnectivity-client,https://github.com/kubernetes-sigs/apiserver-network-proxy/blob/konnectivity-client/v0.31.1/konnectivity-client/LICENSE,Apache-2.0 sigs.k8s.io/controller-runtime,https://github.com/kubernetes-sigs/controller-runtime/blob/v0.19.0/LICENSE,Apache-2.0 sigs.k8s.io/gateway-api,https://github.com/kubernetes-sigs/gateway-api/blob/v1.1.0/LICENSE,Apache-2.0 -sigs.k8s.io/json,https://github.com/kubernetes-sigs/json/blob/bc3834ca7abd/LICENSE,Apache-2.0 -sigs.k8s.io/json,https://github.com/kubernetes-sigs/json/blob/bc3834ca7abd/LICENSE,BSD-3-Clause -sigs.k8s.io/structured-merge-diff/v4,https://github.com/kubernetes-sigs/structured-merge-diff/blob/v4.4.1/LICENSE,Apache-2.0 +sigs.k8s.io/json,https://github.com/kubernetes-sigs/json/blob/cfa47c3a1cc8/LICENSE,Apache-2.0 +sigs.k8s.io/json,https://github.com/kubernetes-sigs/json/blob/cfa47c3a1cc8/LICENSE,BSD-3-Clause +sigs.k8s.io/structured-merge-diff/v4,https://github.com/kubernetes-sigs/structured-merge-diff/blob/v4.5.0/LICENSE,Apache-2.0 sigs.k8s.io/yaml,https://github.com/kubernetes-sigs/yaml/blob/v1.4.0/LICENSE,MIT sigs.k8s.io/yaml,https://github.com/kubernetes-sigs/yaml/blob/v1.4.0/LICENSE,Apache-2.0 sigs.k8s.io/yaml,https://github.com/kubernetes-sigs/yaml/blob/v1.4.0/LICENSE,BSD-3-Clause diff --git a/vendor/github.com/cert-manager/cert-manager/pkg/apis/acme/v1/types_issuer.go b/vendor/github.com/cert-manager/cert-manager/pkg/apis/acme/v1/types_issuer.go index 04daf9dec5f..7f6365e25a8 100644 --- a/vendor/github.com/cert-manager/cert-manager/pkg/apis/acme/v1/types_issuer.go +++ b/vendor/github.com/cert-manager/cert-manager/pkg/apis/acme/v1/types_issuer.go @@ -710,6 +710,10 @@ type AzureManagedIdentity struct { // Cannot be used for Azure Managed Service Identity // +optional ResourceID string `json:"resourceID,omitempty"` + + // tenant ID of the managed identity, can not be used at the same time as resourceID + // +optional + TenantID string `json:"tenantID,omitempty"` } // +kubebuilder:validation:Enum=AzurePublicCloud;AzureChinaCloud;AzureGermanCloud;AzureUSGovernmentCloud diff --git a/vendor/github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1/types.go b/vendor/github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1/types.go index 1afeedf022e..4b0c35a785e 100644 --- a/vendor/github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1/types.go +++ b/vendor/github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1/types.go @@ -294,6 +294,9 @@ const ( JKSSecretKey = "keystore.jks" // Data Entry Name in the Secret resource for JKS containing Certificate Authority JKSTruststoreKey = "truststore.jks" + + // The password used to encrypt the keystore and truststore + KeystorePassword = "keystorePassword" ) // DefaultKeyUsages contains the default list of key usages diff --git a/vendor/github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1/types_certificate.go b/vendor/github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1/types_certificate.go index 68e2ccfb753..89979e7accf 100644 --- a/vendor/github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1/types_certificate.go +++ b/vendor/github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1/types_certificate.go @@ -458,13 +458,13 @@ type CertificateKeystores struct { PKCS12 *PKCS12Keystore `json:"pkcs12,omitempty"` } -// JKS configures options for storing a JKS keystore in the `spec.secretName` -// Secret resource. +// JKS configures options for storing a JKS keystore in the target secret. +// Either PasswordSecretRef or Password must be provided. type JKSKeystore struct { // Create enables JKS keystore creation for the Certificate. // If true, a file named `keystore.jks` will be created in the target // Secret resource, encrypted using the password stored in - // `passwordSecretRef`. + // `passwordSecretRef` or `password`. // The keystore file will be updated immediately. // If the issuer provided a CA certificate, a file named `truststore.jks` // will also be created in the target Secret resource, encrypted using the @@ -472,14 +472,23 @@ type JKSKeystore struct { // containing the issuing Certificate Authority Create bool `json:"create"` - // PasswordSecretRef is a reference to a key in a Secret resource - // containing the password used to encrypt the JKS keystore. - PasswordSecretRef cmmeta.SecretKeySelector `json:"passwordSecretRef"` - // Alias specifies the alias of the key in the keystore, required by the JKS format. // If not provided, the default alias `certificate` will be used. // +optional Alias *string `json:"alias,omitempty"` + + // PasswordSecretRef is a reference to a non-empty key in a Secret resource + // containing the password used to encrypt the JKS keystore. + // Mutually exclusive with password. + // One of password or passwordSecretRef must provide a password with a non-zero length. + // +optional + PasswordSecretRef cmmeta.SecretKeySelector `json:"passwordSecretRef,omitempty"` + + // Password provides a literal password used to encrypt the JKS keystore. + // Mutually exclusive with passwordSecretRef. + // One of password or passwordSecretRef must provide a password with a non-zero length. + // +optional + Password *string `json:"password,omitempty"` } // PKCS12 configures options for storing a PKCS12 keystore in the @@ -488,7 +497,7 @@ type PKCS12Keystore struct { // Create enables PKCS12 keystore creation for the Certificate. // If true, a file named `keystore.p12` will be created in the target // Secret resource, encrypted using the password stored in - // `passwordSecretRef`. + // `passwordSecretRef` or in `password`. // The keystore file will be updated immediately. // If the issuer provided a CA certificate, a file named `truststore.p12` will // also be created in the target Secret resource, encrypted using the @@ -496,10 +505,6 @@ type PKCS12Keystore struct { // Authority Create bool `json:"create"` - // PasswordSecretRef is a reference to a key in a Secret resource - // containing the password used to encrypt the PKCS12 keystore. - PasswordSecretRef cmmeta.SecretKeySelector `json:"passwordSecretRef"` - // Profile specifies the key and certificate encryption algorithms and the HMAC algorithm // used to create the PKCS12 keystore. Default value is `LegacyRC2` for backward compatibility. // @@ -511,6 +516,19 @@ type PKCS12Keystore struct { // in reality, because the unencrypted certificate and private key are also stored in the Secret. // +optional Profile PKCS12Profile `json:"profile,omitempty"` + + // PasswordSecretRef is a reference to a non-empty key in a Secret resource + // containing the password used to encrypt the PKCS#12 keystore. + // Mutually exclusive with password. + // One of password or passwordSecretRef must provide a password with a non-zero length. + // +optional + PasswordSecretRef cmmeta.SecretKeySelector `json:"passwordSecretRef,omitempty"` + + // Password provides a literal password used to encrypt the PKCS#12 keystore. + // Mutually exclusive with passwordSecretRef. + // One of password or passwordSecretRef must provide a password with a non-zero length. + // +optional + Password *string `json:"password,omitempty"` } // +kubebuilder:validation:Enum=LegacyRC2;LegacyDES;Modern2023 diff --git a/vendor/github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1/zz_generated.deepcopy.go b/vendor/github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1/zz_generated.deepcopy.go index 9c024c6afe6..e889ecf1a9a 100644 --- a/vendor/github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1/zz_generated.deepcopy.go +++ b/vendor/github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1/zz_generated.deepcopy.go @@ -134,7 +134,7 @@ func (in *CertificateKeystores) DeepCopyInto(out *CertificateKeystores) { if in.PKCS12 != nil { in, out := &in.PKCS12, &out.PKCS12 *out = new(PKCS12Keystore) - **out = **in + (*in).DeepCopyInto(*out) } return } @@ -785,12 +785,17 @@ func (in *IssuerStatus) DeepCopy() *IssuerStatus { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *JKSKeystore) DeepCopyInto(out *JKSKeystore) { *out = *in - out.PasswordSecretRef = in.PasswordSecretRef if in.Alias != nil { in, out := &in.Alias, &out.Alias *out = new(string) **out = **in } + out.PasswordSecretRef = in.PasswordSecretRef + if in.Password != nil { + in, out := &in.Password, &out.Password + *out = new(string) + **out = **in + } return } @@ -886,6 +891,11 @@ func (in *OtherName) DeepCopy() *OtherName { func (in *PKCS12Keystore) DeepCopyInto(out *PKCS12Keystore) { *out = *in out.PasswordSecretRef = in.PasswordSecretRef + if in.Password != nil { + in, out := &in.Password, &out.Password + *out = new(string) + **out = **in + } return } diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/CESQLLexer.g4 b/vendor/github.com/cloudevents/sdk-go/sql/v2/CESQLLexer.g4 index d83124abd3b..a889c058a46 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/CESQLLexer.g4 +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/CESQLLexer.g4 @@ -70,7 +70,7 @@ FALSE: 'FALSE'; DQUOTED_STRING_LITERAL: DQUOTA_STRING; SQUOTED_STRING_LITERAL: SQUOTA_STRING; -INTEGER_LITERAL: ('+' | '-')? INT_DIGIT+; +INTEGER_LITERAL: INT_DIGIT+; // Identifiers diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/README.md b/vendor/github.com/cloudevents/sdk-go/sql/v2/README.md index 948f48f416d..f45641d973d 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/README.md +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/README.md @@ -18,54 +18,6 @@ expression, err := cesqlparser.Parse("subject = 'Hello world'") res, err := expression.Evaluate(event) ``` -Add a user defined function -```go -import ( - cesql "github.com/cloudevents/sdk-go/sql/v2" - cefn "github.com/cloudevents/sdk-go/sql/v2/function" - cesqlparser "github.com/cloudevents/sdk-go/sql/v2/parser" - ceruntime "github.com/cloudevents/sdk-go/sql/v2/runtime" - cloudevents "github.com/cloudevents/sdk-go/v2" -) - -// Create a test event -event := cloudevents.NewEvent() -event.SetID("aaaa-bbbb-dddd") -event.SetSource("https://my-source") -event.SetType("dev.tekton.event") - -// Create and add a new user defined function -var HasPrefixFunction cesql.Function = cefn.NewFunction( - "HASPREFIX", - []cesql.Type{cesql.StringType, cesql.StringType}, - nil, - func(event cloudevents.Event, i []interface{}) (interface{}, error) { - str := i[0].(string) - prefix := i[1].(string) - - return strings.HasPrefix(str, prefix), nil - }, -) - -err := ceruntime.AddFunction(HasPrefixFunction) - -// parse the expression -expression, err := cesqlparser.Parse("HASPREFIX(type, 'dev.tekton.event')") - if err != nil { - fmt.Println("parser err: ", err) - os.Exit(1) - } - -// Evalute the expression with the test event -res, err := expression.Evaluate(event) - -if res.(bool) { - fmt.Println("Event type has the prefix") -} else { - fmt.Println("Event type doesn't have the prefix") -} -``` - ## Development guide To regenerate the parser, make sure you have [ANTLR4 installed](https://github.com/antlr/antlr4/blob/master/doc/getting-started.md) and then run: diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/errors/errors.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/errors/errors.go deleted file mode 100644 index 207ce55f34e..00000000000 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/errors/errors.go +++ /dev/null @@ -1,152 +0,0 @@ -/* - Copyright 2024 The CloudEvents Authors - SPDX-License-Identifier: Apache-2.0 -*/ - -package errors - -import ( - "fmt" - "strings" -) - -type errorKind int - -const ( - parseError = iota - mathError - castError - missingAttributeError - missingFunctionError - functionEvaluationError - dummyLastError // always add new error classes ABOVE this error -) - -type cesqlError struct { - kind errorKind - message string -} - -func (eKind errorKind) String() string { - switch eKind { - case parseError: - return "parse error" - case mathError: - return "math error" - case castError: - return "cast error" - case missingAttributeError: - return "missing attribute error" - case missingFunctionError: - return "missing function error" - case functionEvaluationError: - return "function evaluation error" - default: - return "generic error" - } - -} - -func (cerr cesqlError) Error() string { - return fmt.Sprintf("%s: %s", cerr.kind, cerr.message) -} - -func NewParseError(errs []error) error { - if len(errs) == 0 { - return nil - } - - errorMessages := make([]string, 0, len(errs)) - for _, err := range errs { - errorMessages = append(errorMessages, err.Error()) - } - - return cesqlError{ - kind: parseError, - message: strings.Join(errorMessages, "|"), - } -} - -func IsParseError(err error) bool { - if cesqlErr, ok := err.(cesqlError); ok { - return cesqlErr.kind == parseError - } - return false -} - -func IsMathError(err error) bool { - if cesqlErr, ok := err.(cesqlError); ok { - return cesqlErr.kind == mathError - } - return false -} - -func NewMathError(message string) error { - return cesqlError{ - kind: mathError, - message: message, - } -} - -func IsCastError(err error) bool { - if cesqlErr, ok := err.(cesqlError); ok { - return cesqlErr.kind == castError - } - return false -} - -func NewCastError(err error) error { - return cesqlError{ - kind: castError, - message: err.Error(), - } -} - -func IsMissingAttributeError(err error) bool { - if cesqlErr, ok := err.(cesqlError); ok { - return cesqlErr.kind == missingAttributeError - } - return false -} - -func NewMissingAttributeError(attribute string) error { - return cesqlError{ - kind: missingAttributeError, - message: attribute, - } -} - -func IsMissingFunctionError(err error) bool { - if cesqlErr, ok := err.(cesqlError); ok { - return cesqlErr.kind == missingFunctionError - } - return false -} - -func NewMissingFunctionError(function string) error { - return cesqlError{ - kind: missingFunctionError, - message: function, - } -} - -func IsFunctionEvaluationError(err error) bool { - if cesqlErr, ok := err.(cesqlError); ok { - return cesqlErr.kind == functionEvaluationError - } - return false -} - -func NewFunctionEvaluationError(err error) error { - return cesqlError{ - kind: functionEvaluationError, - message: err.Error(), - } -} - -func IsGenericError(err error) bool { - if cesqlErr, ok := err.(cesqlError); ok { - return cesqlErr.kind < 0 || cesqlErr.kind >= dummyLastError - } - return false -} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/comparison_expressions.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/comparison_expressions.go index a39ad3ce793..97449073738 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/comparison_expressions.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/comparison_expressions.go @@ -19,17 +19,17 @@ type equalExpression struct { func (s equalExpression) Evaluate(event cloudevents.Event) (interface{}, error) { leftVal, err := s.left.Evaluate(event) if err != nil { - return false, err + return nil, err } rightVal, err := s.right.Evaluate(event) if err != nil { - return false, err + return nil, err } leftVal, err = utils.Cast(leftVal, cesql.TypeFromVal(rightVal)) if err != nil { - return false, err + return nil, err } return (leftVal == rightVal) == s.equal, nil diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/function_invocation_expression.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/function_invocation_expression.go index 577272f268f..94e383aa158 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/function_invocation_expression.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/function_invocation_expression.go @@ -9,7 +9,6 @@ import ( "fmt" cesql "github.com/cloudevents/sdk-go/sql/v2" - sqlerrors "github.com/cloudevents/sdk-go/sql/v2/errors" "github.com/cloudevents/sdk-go/sql/v2/runtime" "github.com/cloudevents/sdk-go/sql/v2/utils" cloudevents "github.com/cloudevents/sdk-go/v2" @@ -23,44 +22,31 @@ type functionInvocationExpression struct { func (expr functionInvocationExpression) Evaluate(event cloudevents.Event) (interface{}, error) { fn := runtime.ResolveFunction(expr.name, len(expr.argumentsExpression)) if fn == nil { - return false, sqlerrors.NewMissingFunctionError(expr.name) + return nil, fmt.Errorf("cannot resolve function %s", expr.name) } args := make([]interface{}, len(expr.argumentsExpression)) - defaultVal := fn.ReturnType().ZeroValue() - for i, expr := range expr.argumentsExpression { arg, err := expr.Evaluate(event) if err != nil { - return defaultVal, err + return nil, err } argType := fn.ArgType(i) if argType == nil { - return defaultVal, sqlerrors.NewFunctionEvaluationError(fmt.Errorf("cannot resolve arg type at index %d for function %s", i, fn.Name())) + return nil, fmt.Errorf("cannot resolve arg type at index %d", i) } arg, err = utils.Cast(arg, *argType) if err != nil { - return defaultVal, err + return nil, err } args[i] = arg } - result, err := fn.Run(event, args) - if result == nil { - if err != nil { - err = sqlerrors.NewFunctionEvaluationError(fmt.Errorf("function %s encountered error %w and did not return any value, defaulting to the default value for the function", fn.Name(), err)) - } else { - err = sqlerrors.NewFunctionEvaluationError(fmt.Errorf("function %s did not return any value, defaulting to the default value for the function", fn.Name())) - } - - return defaultVal, err - } - - return result, err + return fn.Run(event, args) } func NewFunctionInvocationExpression(name string, argumentsExpression []cesql.Expression) cesql.Expression { diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/identifier_expression.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/identifier_expression.go index fe85052f9c6..265a3b463f5 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/identifier_expression.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/identifier_expression.go @@ -6,8 +6,9 @@ package expression import ( + "fmt" + cesql "github.com/cloudevents/sdk-go/sql/v2" - sqlerrors "github.com/cloudevents/sdk-go/sql/v2/errors" "github.com/cloudevents/sdk-go/sql/v2/utils" cloudevents "github.com/cloudevents/sdk-go/v2" ) @@ -19,7 +20,7 @@ type identifierExpression struct { func (l identifierExpression) Evaluate(event cloudevents.Event) (interface{}, error) { value := utils.GetAttribute(event, l.identifier) if value == nil { - return false, sqlerrors.NewMissingAttributeError(l.identifier) + return nil, fmt.Errorf("missing attribute '%s'", l.identifier) } return value, nil diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/in_expression.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/in_expression.go index ef1c587c04c..b45a421ceab 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/in_expression.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/in_expression.go @@ -19,18 +19,18 @@ type inExpression struct { func (l inExpression) Evaluate(event cloudevents.Event) (interface{}, error) { leftValue, err := l.leftExpression.Evaluate(event) if err != nil { - return false, err + return nil, err } for _, rightExpression := range l.setExpression { rightValue, err := rightExpression.Evaluate(event) if err != nil { - return false, err + return nil, err } rightValue, err = utils.Cast(rightValue, cesql.TypeFromVal(leftValue)) if err != nil { - return false, err + return nil, err } if leftValue == rightValue { diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/integer_comparison_expressions.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/integer_comparison_expressions.go index 12e529b79a1..13a70a974c0 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/integer_comparison_expressions.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/integer_comparison_expressions.go @@ -19,22 +19,22 @@ type integerComparisonExpression struct { func (s integerComparisonExpression) Evaluate(event cloudevents.Event) (interface{}, error) { leftVal, err := s.left.Evaluate(event) if err != nil { - return false, err + return nil, err } rightVal, err := s.right.Evaluate(event) if err != nil { - return false, err + return nil, err } leftVal, err = utils.Cast(leftVal, cesql.IntegerType) if err != nil { - return false, err + return nil, err } rightVal, err = utils.Cast(rightVal, cesql.IntegerType) if err != nil { - return false, err + return nil, err } return s.fn(leftVal.(int32), rightVal.(int32)), nil diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/like_expression.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/like_expression.go index ed43db49415..5f557fa5ac7 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/like_expression.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/like_expression.go @@ -6,6 +6,9 @@ package expression import ( + "regexp" + "strings" + cesql "github.com/cloudevents/sdk-go/sql/v2" "github.com/cloudevents/sdk-go/sql/v2/utils" cloudevents "github.com/cloudevents/sdk-go/v2" @@ -13,79 +16,84 @@ import ( type likeExpression struct { baseUnaryExpression - pattern string + pattern *regexp.Regexp } func (l likeExpression) Evaluate(event cloudevents.Event) (interface{}, error) { val, err := l.child.Evaluate(event) if err != nil { - return false, err + return nil, err } val, err = utils.Cast(val, cesql.StringType) if err != nil { - return false, err + return nil, err } - return matchString(val.(string), l.pattern), nil - + return l.pattern.MatchString(val.(string)), nil } func NewLikeExpression(child cesql.Expression, pattern string) (cesql.Expression, error) { + // Converting to regex is not the most performant impl, but it works + p, err := convertLikePatternToRegex(pattern) + if err != nil { + return nil, err + } + return likeExpression{ baseUnaryExpression: baseUnaryExpression{ child: child, }, - pattern: pattern, + pattern: p, }, nil } -func matchString(text, pattern string) bool { - textLen := len(text) - patternLen := len(pattern) - textIdx := 0 - patternIdx := 0 - lastWildcardIdx := -1 - lastMatchIdx := 0 +func convertLikePatternToRegex(pattern string) (*regexp.Regexp, error) { + var chunks []string + chunks = append(chunks, "^") - if patternLen == 0 { - return patternLen == textLen - } + var chunk strings.Builder - for textIdx < textLen { - if patternIdx < patternLen-1 && pattern[patternIdx] == '\\' && - ((pattern[patternIdx+1] == '_' || pattern[patternIdx+1] == '%') && - pattern[patternIdx+1] == text[textIdx]) { - // handle escaped characters -> pattern needs to increment two places here - patternIdx += 2 - textIdx += 1 - } else if patternIdx < patternLen && (pattern[patternIdx] == '_' || pattern[patternIdx] == text[textIdx]) { - // handle non escaped characters - textIdx += 1 - patternIdx += 1 - } else if patternIdx < patternLen && pattern[patternIdx] == '%' { - // handle wildcard characters - lastWildcardIdx = patternIdx - lastMatchIdx = textIdx - patternIdx += 1 - } else if lastWildcardIdx != -1 { - // greedy match didn't work, try again from the last known match - patternIdx = lastWildcardIdx + 1 - lastMatchIdx += 1 - textIdx = lastMatchIdx + for i := 0; i < len(pattern); i++ { + if pattern[i] == '\\' && i < len(pattern)-1 { + if pattern[i+1] == '%' { + // \% case + chunk.WriteRune('%') + chunks = append(chunks, "\\Q"+chunk.String()+"\\E") + chunk.Reset() + i++ + continue + } else if pattern[i+1] == '_' { + // \_ case + chunk.WriteRune('_') + chunks = append(chunks, "\\Q"+chunk.String()+"\\E") + chunk.Reset() + i++ + continue + } else { + // if there is an actual literal \ character, we need to include that in the string + chunk.WriteRune('\\') + } + } else if pattern[i] == '_' { + // replace with . + chunks = append(chunks, "\\Q"+chunk.String()+"\\E") + chunk.Reset() + chunks = append(chunks, ".") + } else if pattern[i] == '%' { + // replace with .* + chunks = append(chunks, "\\Q"+chunk.String()+"\\E") + chunk.Reset() + chunks = append(chunks, ".*") } else { - return false + chunk.WriteByte(pattern[i]) } } - // consume remaining pattern characters as long as they are wildcards - for patternIdx < patternLen { - if pattern[patternIdx] != '%' { - return false - } - - patternIdx += 1 + if chunk.Len() != 0 { + chunks = append(chunks, "\\Q"+chunk.String()+"\\E") } - return true + chunks = append(chunks, "$") + + return regexp.Compile(strings.Join(chunks, "")) } diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/logic_expressions.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/logic_expressions.go index 4812debf221..f75a0f9c4e3 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/logic_expressions.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/logic_expressions.go @@ -20,12 +20,12 @@ type logicExpression struct { func (s logicExpression) Evaluate(event cloudevents.Event) (interface{}, error) { leftVal, err := s.left.Evaluate(event) if err != nil { - return false, err + return nil, err } leftVal, err = utils.Cast(leftVal, cesql.BooleanType) if err != nil { - return false, err + return nil, err } // Don't bother to check the other expression unless we need to @@ -38,12 +38,12 @@ func (s logicExpression) Evaluate(event cloudevents.Event) (interface{}, error) rightVal, err := s.right.Evaluate(event) if err != nil { - return false, err + return nil, err } rightVal, err = utils.Cast(rightVal, cesql.BooleanType) if err != nil { - return false, err + return nil, err } return s.fn(leftVal.(bool), rightVal.(bool)), nil diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/math_expressions.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/math_expressions.go index 50b45d70b03..d0378201132 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/math_expressions.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/math_expressions.go @@ -6,8 +6,9 @@ package expression import ( + "errors" + cesql "github.com/cloudevents/sdk-go/sql/v2" - sqlerrors "github.com/cloudevents/sdk-go/sql/v2/errors" "github.com/cloudevents/sdk-go/sql/v2/utils" cloudevents "github.com/cloudevents/sdk-go/v2" ) @@ -20,22 +21,22 @@ type mathExpression struct { func (s mathExpression) Evaluate(event cloudevents.Event) (interface{}, error) { leftVal, err := s.left.Evaluate(event) if err != nil { - return int32(0), err + return nil, err } rightVal, err := s.right.Evaluate(event) if err != nil { - return int32(0), err + return nil, err } leftVal, err = utils.Cast(leftVal, cesql.IntegerType) if err != nil { - return int32(0), err + return nil, err } rightVal, err = utils.Cast(rightVal, cesql.IntegerType) if err != nil { - return int32(0), err + return nil, err } return s.fn(leftVal.(int32), rightVal.(int32)) @@ -85,7 +86,7 @@ func NewModuleExpression(left cesql.Expression, right cesql.Expression) cesql.Ex }, fn: func(x, y int32) (int32, error) { if y == 0 { - return 0, sqlerrors.NewMathError("division by zero") + return 0, errors.New("math error: division by zero") } return x % y, nil }, @@ -100,7 +101,7 @@ func NewDivisionExpression(left cesql.Expression, right cesql.Expression) cesql. }, fn: func(x, y int32) (int32, error) { if y == 0 { - return 0, sqlerrors.NewMathError("division by zero") + return 0, errors.New("math error: division by zero") } return x / y, nil }, diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/negate_expression.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/negate_expression.go index d271f324389..f917a83bf49 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/negate_expression.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/negate_expression.go @@ -16,12 +16,12 @@ type negateExpression baseUnaryExpression func (l negateExpression) Evaluate(event cloudevents.Event) (interface{}, error) { val, err := l.child.Evaluate(event) if err != nil { - return int32(0), err + return nil, err } val, err = utils.Cast(val, cesql.IntegerType) if err != nil { - return int32(0), err + return nil, err } return -(val.(int32)), nil diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/not_expression.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/not_expression.go index a1bedac10ba..7f5e95b9f8c 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/not_expression.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/expression/not_expression.go @@ -16,12 +16,12 @@ type notExpression baseUnaryExpression func (l notExpression) Evaluate(event cloudevents.Event) (interface{}, error) { val, err := l.child.Evaluate(event) if err != nil { - return false, err + return nil, err } val, err = utils.Cast(val, cesql.BooleanType) if err != nil { - return false, err + return nil, err } return !(val.(bool)), nil diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/function.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/function.go index fb7efb65552..1502a3d2f8d 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/function.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/function.go @@ -12,7 +12,6 @@ type Function interface { Arity() int IsVariadic() bool ArgType(index int) *Type - ReturnType() Type Run(event cloudevents.Event, arguments []interface{}) (interface{}, error) } diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/function/casting_functions.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/function/casting_functions.go index 35c1d562eba..91069de8096 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/function/casting_functions.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/function/casting_functions.go @@ -15,7 +15,6 @@ var IntFunction function = function{ name: "INT", fixedArgs: []cesql.Type{cesql.AnyType}, variadicArgs: nil, - returnType: cesql.IntegerType, fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { return utils.Cast(i[0], cesql.IntegerType) }, @@ -25,7 +24,6 @@ var BoolFunction function = function{ name: "BOOL", fixedArgs: []cesql.Type{cesql.AnyType}, variadicArgs: nil, - returnType: cesql.BooleanType, fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { return utils.Cast(i[0], cesql.BooleanType) }, @@ -35,7 +33,6 @@ var StringFunction function = function{ name: "STRING", fixedArgs: []cesql.Type{cesql.AnyType}, variadicArgs: nil, - returnType: cesql.StringType, fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { return utils.Cast(i[0], cesql.StringType) }, @@ -45,7 +42,6 @@ var IsIntFunction function = function{ name: "IS_INT", fixedArgs: []cesql.Type{cesql.AnyType}, variadicArgs: nil, - returnType: cesql.BooleanType, fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { return utils.CanCast(i[0], cesql.IntegerType), nil }, @@ -55,7 +51,6 @@ var IsBoolFunction function = function{ name: "IS_BOOL", fixedArgs: []cesql.Type{cesql.AnyType}, variadicArgs: nil, - returnType: cesql.BooleanType, fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { return utils.CanCast(i[0], cesql.BooleanType), nil }, diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/function/function.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/function/function.go index ddc3d0489fe..4ad61faed6b 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/function/function.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/function/function.go @@ -10,14 +10,11 @@ import ( cloudevents "github.com/cloudevents/sdk-go/v2" ) -type FuncType func(cloudevents.Event, []interface{}) (interface{}, error) - type function struct { name string fixedArgs []cesql.Type variadicArgs *cesql.Type - returnType cesql.Type - fn FuncType + fn func(cloudevents.Event, []interface{}) (interface{}, error) } func (f function) Name() string { @@ -39,24 +36,6 @@ func (f function) ArgType(index int) *cesql.Type { return f.variadicArgs } -func (f function) ReturnType() cesql.Type { - return f.returnType -} - func (f function) Run(event cloudevents.Event, arguments []interface{}) (interface{}, error) { return f.fn(event, arguments) } - -func NewFunction(name string, - fixedArgs []cesql.Type, - variadicArgs *cesql.Type, - returnType cesql.Type, - fn FuncType) cesql.Function { - return function{ - name: name, - fixedArgs: fixedArgs, - variadicArgs: variadicArgs, - returnType: returnType, - fn: fn, - } -} diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/function/integer_functions.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/function/integer_functions.go index f7f3f7225b7..4aaf64f2272 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/function/integer_functions.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/function/integer_functions.go @@ -7,21 +7,15 @@ package function import ( cesql "github.com/cloudevents/sdk-go/sql/v2" - sqlerrors "github.com/cloudevents/sdk-go/sql/v2/errors" cloudevents "github.com/cloudevents/sdk-go/v2" - "math" ) var AbsFunction function = function{ name: "ABS", fixedArgs: []cesql.Type{cesql.IntegerType}, variadicArgs: nil, - returnType: cesql.IntegerType, fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { x := i[0].(int32) - if x == math.MinInt32 { - return int32(math.MaxInt32), sqlerrors.NewMathError("integer overflow while computing ABS") - } if x < 0 { return -x, nil } diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/function/string_functions.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/function/string_functions.go index 66eeb2c1637..2d0d7e4a93e 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/function/string_functions.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/function/string_functions.go @@ -10,7 +10,6 @@ import ( "strings" cesql "github.com/cloudevents/sdk-go/sql/v2" - sqlerrors "github.com/cloudevents/sdk-go/sql/v2/errors" cloudevents "github.com/cloudevents/sdk-go/v2" ) @@ -18,7 +17,6 @@ var LengthFunction function = function{ name: "LENGTH", fixedArgs: []cesql.Type{cesql.StringType}, variadicArgs: nil, - returnType: cesql.IntegerType, fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { return int32(len(i[0].(string))), nil }, @@ -27,7 +25,6 @@ var LengthFunction function = function{ var ConcatFunction function = function{ name: "CONCAT", variadicArgs: cesql.TypePtr(cesql.StringType), - returnType: cesql.StringType, fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { var sb strings.Builder for _, v := range i { @@ -41,7 +38,6 @@ var ConcatWSFunction function = function{ name: "CONCAT_WS", fixedArgs: []cesql.Type{cesql.StringType}, variadicArgs: cesql.TypePtr(cesql.StringType), - returnType: cesql.StringType, fn: func(event cloudevents.Event, args []interface{}) (interface{}, error) { if len(args) == 1 { return "", nil @@ -59,36 +55,32 @@ var ConcatWSFunction function = function{ } var LowerFunction function = function{ - name: "LOWER", - fixedArgs: []cesql.Type{cesql.StringType}, - returnType: cesql.StringType, + name: "LOWER", + fixedArgs: []cesql.Type{cesql.StringType}, fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { return strings.ToLower(i[0].(string)), nil }, } var UpperFunction function = function{ - name: "UPPER", - fixedArgs: []cesql.Type{cesql.StringType}, - returnType: cesql.StringType, + name: "UPPER", + fixedArgs: []cesql.Type{cesql.StringType}, fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { return strings.ToUpper(i[0].(string)), nil }, } var TrimFunction function = function{ - name: "TRIM", - fixedArgs: []cesql.Type{cesql.StringType}, - returnType: cesql.StringType, + name: "TRIM", + fixedArgs: []cesql.Type{cesql.StringType}, fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { return strings.TrimSpace(i[0].(string)), nil }, } var LeftFunction function = function{ - name: "LEFT", - fixedArgs: []cesql.Type{cesql.StringType, cesql.IntegerType}, - returnType: cesql.StringType, + name: "LEFT", + fixedArgs: []cesql.Type{cesql.StringType, cesql.IntegerType}, fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { str := i[0].(string) y := int(i[1].(int32)) @@ -98,7 +90,7 @@ var LeftFunction function = function{ } if y < 0 { - return str, sqlerrors.NewFunctionEvaluationError(fmt.Errorf("LEFT y argument is < 0: %d", y)) + return nil, fmt.Errorf("LEFT y argument is < 0: %d", y) } return str[0:y], nil @@ -106,9 +98,8 @@ var LeftFunction function = function{ } var RightFunction function = function{ - name: "RIGHT", - fixedArgs: []cesql.Type{cesql.StringType, cesql.IntegerType}, - returnType: cesql.StringType, + name: "RIGHT", + fixedArgs: []cesql.Type{cesql.StringType, cesql.IntegerType}, fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { str := i[0].(string) y := int(i[1].(int32)) @@ -118,7 +109,7 @@ var RightFunction function = function{ } if y < 0 { - return str, sqlerrors.NewFunctionEvaluationError(fmt.Errorf("RIGHT y argument is < 0: %d", y)) + return nil, fmt.Errorf("RIGHT y argument is < 0: %d", y) } return str[len(str)-y:], nil @@ -126,9 +117,8 @@ var RightFunction function = function{ } var SubstringFunction function = function{ - name: "SUBSTRING", - fixedArgs: []cesql.Type{cesql.StringType, cesql.IntegerType}, - returnType: cesql.StringType, + name: "SUBSTRING", + fixedArgs: []cesql.Type{cesql.StringType, cesql.IntegerType}, fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { str := i[0].(string) pos := int(i[1].(int32)) @@ -138,7 +128,7 @@ var SubstringFunction function = function{ } if pos < -len(str) || pos > len(str) { - return "", sqlerrors.NewFunctionEvaluationError(fmt.Errorf("SUBSTRING invalid pos argument: %d", pos)) + return "", fmt.Errorf("SUBSTRING invalid pos argument: %d", pos) } var beginning int @@ -153,9 +143,8 @@ var SubstringFunction function = function{ } var SubstringWithLengthFunction function = function{ - name: "SUBSTRING", - fixedArgs: []cesql.Type{cesql.StringType, cesql.IntegerType, cesql.IntegerType}, - returnType: cesql.StringType, + name: "SUBSTRING", + fixedArgs: []cesql.Type{cesql.StringType, cesql.IntegerType, cesql.IntegerType}, fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) { str := i[0].(string) pos := int(i[1].(int32)) @@ -166,7 +155,7 @@ var SubstringWithLengthFunction function = function{ } if pos < -len(str) || pos > len(str) { - return "", sqlerrors.NewFunctionEvaluationError(fmt.Errorf("SUBSTRING invalid pos argument: %d", pos)) + return "", fmt.Errorf("SUBSTRING invalid pos argument: %d", pos) } var beginning int diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/CESQLParserLexer.interp b/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/CESQLParserLexer.interp index befa543b494..f758513dbe9 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/CESQLParserLexer.interp +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/CESQLParserLexer.interp @@ -119,4 +119,4 @@ mode names: DEFAULT_MODE atn: -[4, 0, 33, 238, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 1, 0, 4, 0, 81, 8, 0, 11, 0, 12, 0, 82, 1, 0, 1, 0, 1, 1, 4, 1, 88, 8, 1, 11, 1, 12, 1, 89, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 5, 2, 98, 8, 2, 10, 2, 12, 2, 101, 9, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 5, 3, 111, 8, 3, 10, 3, 12, 3, 114, 9, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 5, 5, 122, 8, 5, 10, 5, 12, 5, 125, 9, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11, 1, 11, 3, 11, 139, 8, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 35, 3, 35, 215, 8, 35, 1, 35, 4, 35, 218, 8, 35, 11, 35, 12, 35, 219, 1, 36, 4, 36, 223, 8, 36, 11, 36, 12, 36, 224, 1, 37, 4, 37, 228, 8, 37, 11, 37, 12, 37, 229, 1, 38, 1, 38, 5, 38, 234, 8, 38, 10, 38, 12, 38, 237, 9, 38, 0, 0, 39, 1, 1, 3, 0, 5, 0, 7, 0, 9, 0, 11, 0, 13, 2, 15, 3, 17, 4, 19, 5, 21, 6, 23, 0, 25, 7, 27, 8, 29, 9, 31, 10, 33, 11, 35, 12, 37, 13, 39, 14, 41, 15, 43, 16, 45, 17, 47, 18, 49, 19, 51, 20, 53, 21, 55, 22, 57, 23, 59, 24, 61, 25, 63, 26, 65, 27, 67, 28, 69, 29, 71, 30, 73, 31, 75, 32, 77, 33, 1, 0, 9, 3, 0, 9, 10, 13, 13, 32, 32, 3, 0, 48, 57, 65, 90, 97, 122, 2, 0, 34, 34, 92, 92, 2, 0, 39, 39, 92, 92, 1, 0, 48, 57, 1, 0, 65, 90, 2, 0, 65, 90, 95, 95, 2, 0, 43, 43, 45, 45, 2, 0, 65, 90, 97, 122, 246, 0, 1, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 1, 80, 1, 0, 0, 0, 3, 87, 1, 0, 0, 0, 5, 91, 1, 0, 0, 0, 7, 104, 1, 0, 0, 0, 9, 117, 1, 0, 0, 0, 11, 119, 1, 0, 0, 0, 13, 126, 1, 0, 0, 0, 15, 128, 1, 0, 0, 0, 17, 130, 1, 0, 0, 0, 19, 132, 1, 0, 0, 0, 21, 134, 1, 0, 0, 0, 23, 138, 1, 0, 0, 0, 25, 140, 1, 0, 0, 0, 27, 144, 1, 0, 0, 0, 29, 147, 1, 0, 0, 0, 31, 151, 1, 0, 0, 0, 33, 155, 1, 0, 0, 0, 35, 157, 1, 0, 0, 0, 37, 159, 1, 0, 0, 0, 39, 161, 1, 0, 0, 0, 41, 163, 1, 0, 0, 0, 43, 165, 1, 0, 0, 0, 45, 167, 1, 0, 0, 0, 47, 170, 1, 0, 0, 0, 49, 172, 1, 0, 0, 0, 51, 175, 1, 0, 0, 0, 53, 177, 1, 0, 0, 0, 55, 180, 1, 0, 0, 0, 57, 183, 1, 0, 0, 0, 59, 188, 1, 0, 0, 0, 61, 195, 1, 0, 0, 0, 63, 198, 1, 0, 0, 0, 65, 203, 1, 0, 0, 0, 67, 209, 1, 0, 0, 0, 69, 211, 1, 0, 0, 0, 71, 214, 1, 0, 0, 0, 73, 222, 1, 0, 0, 0, 75, 227, 1, 0, 0, 0, 77, 231, 1, 0, 0, 0, 79, 81, 7, 0, 0, 0, 80, 79, 1, 0, 0, 0, 81, 82, 1, 0, 0, 0, 82, 80, 1, 0, 0, 0, 82, 83, 1, 0, 0, 0, 83, 84, 1, 0, 0, 0, 84, 85, 6, 0, 0, 0, 85, 2, 1, 0, 0, 0, 86, 88, 7, 1, 0, 0, 87, 86, 1, 0, 0, 0, 88, 89, 1, 0, 0, 0, 89, 87, 1, 0, 0, 0, 89, 90, 1, 0, 0, 0, 90, 4, 1, 0, 0, 0, 91, 99, 5, 34, 0, 0, 92, 93, 5, 92, 0, 0, 93, 98, 9, 0, 0, 0, 94, 95, 5, 34, 0, 0, 95, 98, 5, 34, 0, 0, 96, 98, 8, 2, 0, 0, 97, 92, 1, 0, 0, 0, 97, 94, 1, 0, 0, 0, 97, 96, 1, 0, 0, 0, 98, 101, 1, 0, 0, 0, 99, 97, 1, 0, 0, 0, 99, 100, 1, 0, 0, 0, 100, 102, 1, 0, 0, 0, 101, 99, 1, 0, 0, 0, 102, 103, 5, 34, 0, 0, 103, 6, 1, 0, 0, 0, 104, 112, 5, 39, 0, 0, 105, 106, 5, 92, 0, 0, 106, 111, 9, 0, 0, 0, 107, 108, 5, 39, 0, 0, 108, 111, 5, 39, 0, 0, 109, 111, 8, 3, 0, 0, 110, 105, 1, 0, 0, 0, 110, 107, 1, 0, 0, 0, 110, 109, 1, 0, 0, 0, 111, 114, 1, 0, 0, 0, 112, 110, 1, 0, 0, 0, 112, 113, 1, 0, 0, 0, 113, 115, 1, 0, 0, 0, 114, 112, 1, 0, 0, 0, 115, 116, 5, 39, 0, 0, 116, 8, 1, 0, 0, 0, 117, 118, 7, 4, 0, 0, 118, 10, 1, 0, 0, 0, 119, 123, 7, 5, 0, 0, 120, 122, 7, 6, 0, 0, 121, 120, 1, 0, 0, 0, 122, 125, 1, 0, 0, 0, 123, 121, 1, 0, 0, 0, 123, 124, 1, 0, 0, 0, 124, 12, 1, 0, 0, 0, 125, 123, 1, 0, 0, 0, 126, 127, 5, 40, 0, 0, 127, 14, 1, 0, 0, 0, 128, 129, 5, 41, 0, 0, 129, 16, 1, 0, 0, 0, 130, 131, 5, 44, 0, 0, 131, 18, 1, 0, 0, 0, 132, 133, 5, 39, 0, 0, 133, 20, 1, 0, 0, 0, 134, 135, 5, 34, 0, 0, 135, 22, 1, 0, 0, 0, 136, 139, 3, 19, 9, 0, 137, 139, 3, 21, 10, 0, 138, 136, 1, 0, 0, 0, 138, 137, 1, 0, 0, 0, 139, 24, 1, 0, 0, 0, 140, 141, 5, 65, 0, 0, 141, 142, 5, 78, 0, 0, 142, 143, 5, 68, 0, 0, 143, 26, 1, 0, 0, 0, 144, 145, 5, 79, 0, 0, 145, 146, 5, 82, 0, 0, 146, 28, 1, 0, 0, 0, 147, 148, 5, 88, 0, 0, 148, 149, 5, 79, 0, 0, 149, 150, 5, 82, 0, 0, 150, 30, 1, 0, 0, 0, 151, 152, 5, 78, 0, 0, 152, 153, 5, 79, 0, 0, 153, 154, 5, 84, 0, 0, 154, 32, 1, 0, 0, 0, 155, 156, 5, 42, 0, 0, 156, 34, 1, 0, 0, 0, 157, 158, 5, 47, 0, 0, 158, 36, 1, 0, 0, 0, 159, 160, 5, 37, 0, 0, 160, 38, 1, 0, 0, 0, 161, 162, 5, 43, 0, 0, 162, 40, 1, 0, 0, 0, 163, 164, 5, 45, 0, 0, 164, 42, 1, 0, 0, 0, 165, 166, 5, 61, 0, 0, 166, 44, 1, 0, 0, 0, 167, 168, 5, 33, 0, 0, 168, 169, 5, 61, 0, 0, 169, 46, 1, 0, 0, 0, 170, 171, 5, 62, 0, 0, 171, 48, 1, 0, 0, 0, 172, 173, 5, 62, 0, 0, 173, 174, 5, 61, 0, 0, 174, 50, 1, 0, 0, 0, 175, 176, 5, 60, 0, 0, 176, 52, 1, 0, 0, 0, 177, 178, 5, 60, 0, 0, 178, 179, 5, 62, 0, 0, 179, 54, 1, 0, 0, 0, 180, 181, 5, 60, 0, 0, 181, 182, 5, 61, 0, 0, 182, 56, 1, 0, 0, 0, 183, 184, 5, 76, 0, 0, 184, 185, 5, 73, 0, 0, 185, 186, 5, 75, 0, 0, 186, 187, 5, 69, 0, 0, 187, 58, 1, 0, 0, 0, 188, 189, 5, 69, 0, 0, 189, 190, 5, 88, 0, 0, 190, 191, 5, 73, 0, 0, 191, 192, 5, 83, 0, 0, 192, 193, 5, 84, 0, 0, 193, 194, 5, 83, 0, 0, 194, 60, 1, 0, 0, 0, 195, 196, 5, 73, 0, 0, 196, 197, 5, 78, 0, 0, 197, 62, 1, 0, 0, 0, 198, 199, 5, 84, 0, 0, 199, 200, 5, 82, 0, 0, 200, 201, 5, 85, 0, 0, 201, 202, 5, 69, 0, 0, 202, 64, 1, 0, 0, 0, 203, 204, 5, 70, 0, 0, 204, 205, 5, 65, 0, 0, 205, 206, 5, 76, 0, 0, 206, 207, 5, 83, 0, 0, 207, 208, 5, 69, 0, 0, 208, 66, 1, 0, 0, 0, 209, 210, 3, 5, 2, 0, 210, 68, 1, 0, 0, 0, 211, 212, 3, 7, 3, 0, 212, 70, 1, 0, 0, 0, 213, 215, 7, 7, 0, 0, 214, 213, 1, 0, 0, 0, 214, 215, 1, 0, 0, 0, 215, 217, 1, 0, 0, 0, 216, 218, 3, 9, 4, 0, 217, 216, 1, 0, 0, 0, 218, 219, 1, 0, 0, 0, 219, 217, 1, 0, 0, 0, 219, 220, 1, 0, 0, 0, 220, 72, 1, 0, 0, 0, 221, 223, 7, 8, 0, 0, 222, 221, 1, 0, 0, 0, 223, 224, 1, 0, 0, 0, 224, 222, 1, 0, 0, 0, 224, 225, 1, 0, 0, 0, 225, 74, 1, 0, 0, 0, 226, 228, 7, 1, 0, 0, 227, 226, 1, 0, 0, 0, 228, 229, 1, 0, 0, 0, 229, 227, 1, 0, 0, 0, 229, 230, 1, 0, 0, 0, 230, 76, 1, 0, 0, 0, 231, 235, 7, 5, 0, 0, 232, 234, 7, 6, 0, 0, 233, 232, 1, 0, 0, 0, 234, 237, 1, 0, 0, 0, 235, 233, 1, 0, 0, 0, 235, 236, 1, 0, 0, 0, 236, 78, 1, 0, 0, 0, 237, 235, 1, 0, 0, 0, 14, 0, 82, 89, 97, 99, 110, 112, 123, 138, 214, 219, 224, 229, 235, 1, 6, 0, 0] \ No newline at end of file +[4, 0, 33, 235, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 1, 0, 4, 0, 81, 8, 0, 11, 0, 12, 0, 82, 1, 0, 1, 0, 1, 1, 4, 1, 88, 8, 1, 11, 1, 12, 1, 89, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 5, 2, 98, 8, 2, 10, 2, 12, 2, 101, 9, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 5, 3, 111, 8, 3, 10, 3, 12, 3, 114, 9, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 5, 5, 122, 8, 5, 10, 5, 12, 5, 125, 9, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11, 1, 11, 3, 11, 139, 8, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 35, 4, 35, 215, 8, 35, 11, 35, 12, 35, 216, 1, 36, 4, 36, 220, 8, 36, 11, 36, 12, 36, 221, 1, 37, 4, 37, 225, 8, 37, 11, 37, 12, 37, 226, 1, 38, 1, 38, 5, 38, 231, 8, 38, 10, 38, 12, 38, 234, 9, 38, 0, 0, 39, 1, 1, 3, 0, 5, 0, 7, 0, 9, 0, 11, 0, 13, 2, 15, 3, 17, 4, 19, 5, 21, 6, 23, 0, 25, 7, 27, 8, 29, 9, 31, 10, 33, 11, 35, 12, 37, 13, 39, 14, 41, 15, 43, 16, 45, 17, 47, 18, 49, 19, 51, 20, 53, 21, 55, 22, 57, 23, 59, 24, 61, 25, 63, 26, 65, 27, 67, 28, 69, 29, 71, 30, 73, 31, 75, 32, 77, 33, 1, 0, 8, 3, 0, 9, 10, 13, 13, 32, 32, 3, 0, 48, 57, 65, 90, 97, 122, 2, 0, 34, 34, 92, 92, 2, 0, 39, 39, 92, 92, 1, 0, 48, 57, 1, 0, 65, 90, 2, 0, 65, 90, 95, 95, 2, 0, 65, 90, 97, 122, 242, 0, 1, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 1, 80, 1, 0, 0, 0, 3, 87, 1, 0, 0, 0, 5, 91, 1, 0, 0, 0, 7, 104, 1, 0, 0, 0, 9, 117, 1, 0, 0, 0, 11, 119, 1, 0, 0, 0, 13, 126, 1, 0, 0, 0, 15, 128, 1, 0, 0, 0, 17, 130, 1, 0, 0, 0, 19, 132, 1, 0, 0, 0, 21, 134, 1, 0, 0, 0, 23, 138, 1, 0, 0, 0, 25, 140, 1, 0, 0, 0, 27, 144, 1, 0, 0, 0, 29, 147, 1, 0, 0, 0, 31, 151, 1, 0, 0, 0, 33, 155, 1, 0, 0, 0, 35, 157, 1, 0, 0, 0, 37, 159, 1, 0, 0, 0, 39, 161, 1, 0, 0, 0, 41, 163, 1, 0, 0, 0, 43, 165, 1, 0, 0, 0, 45, 167, 1, 0, 0, 0, 47, 170, 1, 0, 0, 0, 49, 172, 1, 0, 0, 0, 51, 175, 1, 0, 0, 0, 53, 177, 1, 0, 0, 0, 55, 180, 1, 0, 0, 0, 57, 183, 1, 0, 0, 0, 59, 188, 1, 0, 0, 0, 61, 195, 1, 0, 0, 0, 63, 198, 1, 0, 0, 0, 65, 203, 1, 0, 0, 0, 67, 209, 1, 0, 0, 0, 69, 211, 1, 0, 0, 0, 71, 214, 1, 0, 0, 0, 73, 219, 1, 0, 0, 0, 75, 224, 1, 0, 0, 0, 77, 228, 1, 0, 0, 0, 79, 81, 7, 0, 0, 0, 80, 79, 1, 0, 0, 0, 81, 82, 1, 0, 0, 0, 82, 80, 1, 0, 0, 0, 82, 83, 1, 0, 0, 0, 83, 84, 1, 0, 0, 0, 84, 85, 6, 0, 0, 0, 85, 2, 1, 0, 0, 0, 86, 88, 7, 1, 0, 0, 87, 86, 1, 0, 0, 0, 88, 89, 1, 0, 0, 0, 89, 87, 1, 0, 0, 0, 89, 90, 1, 0, 0, 0, 90, 4, 1, 0, 0, 0, 91, 99, 5, 34, 0, 0, 92, 93, 5, 92, 0, 0, 93, 98, 9, 0, 0, 0, 94, 95, 5, 34, 0, 0, 95, 98, 5, 34, 0, 0, 96, 98, 8, 2, 0, 0, 97, 92, 1, 0, 0, 0, 97, 94, 1, 0, 0, 0, 97, 96, 1, 0, 0, 0, 98, 101, 1, 0, 0, 0, 99, 97, 1, 0, 0, 0, 99, 100, 1, 0, 0, 0, 100, 102, 1, 0, 0, 0, 101, 99, 1, 0, 0, 0, 102, 103, 5, 34, 0, 0, 103, 6, 1, 0, 0, 0, 104, 112, 5, 39, 0, 0, 105, 106, 5, 92, 0, 0, 106, 111, 9, 0, 0, 0, 107, 108, 5, 39, 0, 0, 108, 111, 5, 39, 0, 0, 109, 111, 8, 3, 0, 0, 110, 105, 1, 0, 0, 0, 110, 107, 1, 0, 0, 0, 110, 109, 1, 0, 0, 0, 111, 114, 1, 0, 0, 0, 112, 110, 1, 0, 0, 0, 112, 113, 1, 0, 0, 0, 113, 115, 1, 0, 0, 0, 114, 112, 1, 0, 0, 0, 115, 116, 5, 39, 0, 0, 116, 8, 1, 0, 0, 0, 117, 118, 7, 4, 0, 0, 118, 10, 1, 0, 0, 0, 119, 123, 7, 5, 0, 0, 120, 122, 7, 6, 0, 0, 121, 120, 1, 0, 0, 0, 122, 125, 1, 0, 0, 0, 123, 121, 1, 0, 0, 0, 123, 124, 1, 0, 0, 0, 124, 12, 1, 0, 0, 0, 125, 123, 1, 0, 0, 0, 126, 127, 5, 40, 0, 0, 127, 14, 1, 0, 0, 0, 128, 129, 5, 41, 0, 0, 129, 16, 1, 0, 0, 0, 130, 131, 5, 44, 0, 0, 131, 18, 1, 0, 0, 0, 132, 133, 5, 39, 0, 0, 133, 20, 1, 0, 0, 0, 134, 135, 5, 34, 0, 0, 135, 22, 1, 0, 0, 0, 136, 139, 3, 19, 9, 0, 137, 139, 3, 21, 10, 0, 138, 136, 1, 0, 0, 0, 138, 137, 1, 0, 0, 0, 139, 24, 1, 0, 0, 0, 140, 141, 5, 65, 0, 0, 141, 142, 5, 78, 0, 0, 142, 143, 5, 68, 0, 0, 143, 26, 1, 0, 0, 0, 144, 145, 5, 79, 0, 0, 145, 146, 5, 82, 0, 0, 146, 28, 1, 0, 0, 0, 147, 148, 5, 88, 0, 0, 148, 149, 5, 79, 0, 0, 149, 150, 5, 82, 0, 0, 150, 30, 1, 0, 0, 0, 151, 152, 5, 78, 0, 0, 152, 153, 5, 79, 0, 0, 153, 154, 5, 84, 0, 0, 154, 32, 1, 0, 0, 0, 155, 156, 5, 42, 0, 0, 156, 34, 1, 0, 0, 0, 157, 158, 5, 47, 0, 0, 158, 36, 1, 0, 0, 0, 159, 160, 5, 37, 0, 0, 160, 38, 1, 0, 0, 0, 161, 162, 5, 43, 0, 0, 162, 40, 1, 0, 0, 0, 163, 164, 5, 45, 0, 0, 164, 42, 1, 0, 0, 0, 165, 166, 5, 61, 0, 0, 166, 44, 1, 0, 0, 0, 167, 168, 5, 33, 0, 0, 168, 169, 5, 61, 0, 0, 169, 46, 1, 0, 0, 0, 170, 171, 5, 62, 0, 0, 171, 48, 1, 0, 0, 0, 172, 173, 5, 62, 0, 0, 173, 174, 5, 61, 0, 0, 174, 50, 1, 0, 0, 0, 175, 176, 5, 60, 0, 0, 176, 52, 1, 0, 0, 0, 177, 178, 5, 60, 0, 0, 178, 179, 5, 62, 0, 0, 179, 54, 1, 0, 0, 0, 180, 181, 5, 60, 0, 0, 181, 182, 5, 61, 0, 0, 182, 56, 1, 0, 0, 0, 183, 184, 5, 76, 0, 0, 184, 185, 5, 73, 0, 0, 185, 186, 5, 75, 0, 0, 186, 187, 5, 69, 0, 0, 187, 58, 1, 0, 0, 0, 188, 189, 5, 69, 0, 0, 189, 190, 5, 88, 0, 0, 190, 191, 5, 73, 0, 0, 191, 192, 5, 83, 0, 0, 192, 193, 5, 84, 0, 0, 193, 194, 5, 83, 0, 0, 194, 60, 1, 0, 0, 0, 195, 196, 5, 73, 0, 0, 196, 197, 5, 78, 0, 0, 197, 62, 1, 0, 0, 0, 198, 199, 5, 84, 0, 0, 199, 200, 5, 82, 0, 0, 200, 201, 5, 85, 0, 0, 201, 202, 5, 69, 0, 0, 202, 64, 1, 0, 0, 0, 203, 204, 5, 70, 0, 0, 204, 205, 5, 65, 0, 0, 205, 206, 5, 76, 0, 0, 206, 207, 5, 83, 0, 0, 207, 208, 5, 69, 0, 0, 208, 66, 1, 0, 0, 0, 209, 210, 3, 5, 2, 0, 210, 68, 1, 0, 0, 0, 211, 212, 3, 7, 3, 0, 212, 70, 1, 0, 0, 0, 213, 215, 3, 9, 4, 0, 214, 213, 1, 0, 0, 0, 215, 216, 1, 0, 0, 0, 216, 214, 1, 0, 0, 0, 216, 217, 1, 0, 0, 0, 217, 72, 1, 0, 0, 0, 218, 220, 7, 7, 0, 0, 219, 218, 1, 0, 0, 0, 220, 221, 1, 0, 0, 0, 221, 219, 1, 0, 0, 0, 221, 222, 1, 0, 0, 0, 222, 74, 1, 0, 0, 0, 223, 225, 7, 1, 0, 0, 224, 223, 1, 0, 0, 0, 225, 226, 1, 0, 0, 0, 226, 224, 1, 0, 0, 0, 226, 227, 1, 0, 0, 0, 227, 76, 1, 0, 0, 0, 228, 232, 7, 5, 0, 0, 229, 231, 7, 6, 0, 0, 230, 229, 1, 0, 0, 0, 231, 234, 1, 0, 0, 0, 232, 230, 1, 0, 0, 0, 232, 233, 1, 0, 0, 0, 233, 78, 1, 0, 0, 0, 234, 232, 1, 0, 0, 0, 13, 0, 82, 89, 97, 99, 110, 112, 123, 138, 216, 221, 226, 232, 1, 6, 0, 0] \ No newline at end of file diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/cesqlparser_lexer.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/cesqlparser_lexer.go index 22dc8dacc44..556d8b90986 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/cesqlparser_lexer.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/gen/cesqlparser_lexer.go @@ -67,7 +67,7 @@ func cesqlparserlexerLexerInit() { } staticData.predictionContextCache = antlr.NewPredictionContextCache() staticData.serializedATN = []int32{ - 4, 0, 33, 238, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, + 4, 0, 33, 235, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, @@ -87,90 +87,89 @@ func cesqlparserlexerLexerInit() { 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, - 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 35, 3, 35, 215, 8, 35, 1, 35, 4, 35, - 218, 8, 35, 11, 35, 12, 35, 219, 1, 36, 4, 36, 223, 8, 36, 11, 36, 12, - 36, 224, 1, 37, 4, 37, 228, 8, 37, 11, 37, 12, 37, 229, 1, 38, 1, 38, 5, - 38, 234, 8, 38, 10, 38, 12, 38, 237, 9, 38, 0, 0, 39, 1, 1, 3, 0, 5, 0, - 7, 0, 9, 0, 11, 0, 13, 2, 15, 3, 17, 4, 19, 5, 21, 6, 23, 0, 25, 7, 27, - 8, 29, 9, 31, 10, 33, 11, 35, 12, 37, 13, 39, 14, 41, 15, 43, 16, 45, 17, - 47, 18, 49, 19, 51, 20, 53, 21, 55, 22, 57, 23, 59, 24, 61, 25, 63, 26, - 65, 27, 67, 28, 69, 29, 71, 30, 73, 31, 75, 32, 77, 33, 1, 0, 9, 3, 0, - 9, 10, 13, 13, 32, 32, 3, 0, 48, 57, 65, 90, 97, 122, 2, 0, 34, 34, 92, - 92, 2, 0, 39, 39, 92, 92, 1, 0, 48, 57, 1, 0, 65, 90, 2, 0, 65, 90, 95, - 95, 2, 0, 43, 43, 45, 45, 2, 0, 65, 90, 97, 122, 246, 0, 1, 1, 0, 0, 0, - 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, - 0, 0, 21, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, - 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, - 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, - 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, - 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, - 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, - 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, - 0, 0, 0, 77, 1, 0, 0, 0, 1, 80, 1, 0, 0, 0, 3, 87, 1, 0, 0, 0, 5, 91, 1, - 0, 0, 0, 7, 104, 1, 0, 0, 0, 9, 117, 1, 0, 0, 0, 11, 119, 1, 0, 0, 0, 13, - 126, 1, 0, 0, 0, 15, 128, 1, 0, 0, 0, 17, 130, 1, 0, 0, 0, 19, 132, 1, - 0, 0, 0, 21, 134, 1, 0, 0, 0, 23, 138, 1, 0, 0, 0, 25, 140, 1, 0, 0, 0, - 27, 144, 1, 0, 0, 0, 29, 147, 1, 0, 0, 0, 31, 151, 1, 0, 0, 0, 33, 155, - 1, 0, 0, 0, 35, 157, 1, 0, 0, 0, 37, 159, 1, 0, 0, 0, 39, 161, 1, 0, 0, - 0, 41, 163, 1, 0, 0, 0, 43, 165, 1, 0, 0, 0, 45, 167, 1, 0, 0, 0, 47, 170, - 1, 0, 0, 0, 49, 172, 1, 0, 0, 0, 51, 175, 1, 0, 0, 0, 53, 177, 1, 0, 0, - 0, 55, 180, 1, 0, 0, 0, 57, 183, 1, 0, 0, 0, 59, 188, 1, 0, 0, 0, 61, 195, - 1, 0, 0, 0, 63, 198, 1, 0, 0, 0, 65, 203, 1, 0, 0, 0, 67, 209, 1, 0, 0, - 0, 69, 211, 1, 0, 0, 0, 71, 214, 1, 0, 0, 0, 73, 222, 1, 0, 0, 0, 75, 227, - 1, 0, 0, 0, 77, 231, 1, 0, 0, 0, 79, 81, 7, 0, 0, 0, 80, 79, 1, 0, 0, 0, - 81, 82, 1, 0, 0, 0, 82, 80, 1, 0, 0, 0, 82, 83, 1, 0, 0, 0, 83, 84, 1, - 0, 0, 0, 84, 85, 6, 0, 0, 0, 85, 2, 1, 0, 0, 0, 86, 88, 7, 1, 0, 0, 87, - 86, 1, 0, 0, 0, 88, 89, 1, 0, 0, 0, 89, 87, 1, 0, 0, 0, 89, 90, 1, 0, 0, - 0, 90, 4, 1, 0, 0, 0, 91, 99, 5, 34, 0, 0, 92, 93, 5, 92, 0, 0, 93, 98, - 9, 0, 0, 0, 94, 95, 5, 34, 0, 0, 95, 98, 5, 34, 0, 0, 96, 98, 8, 2, 0, - 0, 97, 92, 1, 0, 0, 0, 97, 94, 1, 0, 0, 0, 97, 96, 1, 0, 0, 0, 98, 101, - 1, 0, 0, 0, 99, 97, 1, 0, 0, 0, 99, 100, 1, 0, 0, 0, 100, 102, 1, 0, 0, - 0, 101, 99, 1, 0, 0, 0, 102, 103, 5, 34, 0, 0, 103, 6, 1, 0, 0, 0, 104, - 112, 5, 39, 0, 0, 105, 106, 5, 92, 0, 0, 106, 111, 9, 0, 0, 0, 107, 108, - 5, 39, 0, 0, 108, 111, 5, 39, 0, 0, 109, 111, 8, 3, 0, 0, 110, 105, 1, - 0, 0, 0, 110, 107, 1, 0, 0, 0, 110, 109, 1, 0, 0, 0, 111, 114, 1, 0, 0, - 0, 112, 110, 1, 0, 0, 0, 112, 113, 1, 0, 0, 0, 113, 115, 1, 0, 0, 0, 114, - 112, 1, 0, 0, 0, 115, 116, 5, 39, 0, 0, 116, 8, 1, 0, 0, 0, 117, 118, 7, - 4, 0, 0, 118, 10, 1, 0, 0, 0, 119, 123, 7, 5, 0, 0, 120, 122, 7, 6, 0, - 0, 121, 120, 1, 0, 0, 0, 122, 125, 1, 0, 0, 0, 123, 121, 1, 0, 0, 0, 123, - 124, 1, 0, 0, 0, 124, 12, 1, 0, 0, 0, 125, 123, 1, 0, 0, 0, 126, 127, 5, - 40, 0, 0, 127, 14, 1, 0, 0, 0, 128, 129, 5, 41, 0, 0, 129, 16, 1, 0, 0, - 0, 130, 131, 5, 44, 0, 0, 131, 18, 1, 0, 0, 0, 132, 133, 5, 39, 0, 0, 133, - 20, 1, 0, 0, 0, 134, 135, 5, 34, 0, 0, 135, 22, 1, 0, 0, 0, 136, 139, 3, - 19, 9, 0, 137, 139, 3, 21, 10, 0, 138, 136, 1, 0, 0, 0, 138, 137, 1, 0, - 0, 0, 139, 24, 1, 0, 0, 0, 140, 141, 5, 65, 0, 0, 141, 142, 5, 78, 0, 0, - 142, 143, 5, 68, 0, 0, 143, 26, 1, 0, 0, 0, 144, 145, 5, 79, 0, 0, 145, - 146, 5, 82, 0, 0, 146, 28, 1, 0, 0, 0, 147, 148, 5, 88, 0, 0, 148, 149, - 5, 79, 0, 0, 149, 150, 5, 82, 0, 0, 150, 30, 1, 0, 0, 0, 151, 152, 5, 78, - 0, 0, 152, 153, 5, 79, 0, 0, 153, 154, 5, 84, 0, 0, 154, 32, 1, 0, 0, 0, - 155, 156, 5, 42, 0, 0, 156, 34, 1, 0, 0, 0, 157, 158, 5, 47, 0, 0, 158, - 36, 1, 0, 0, 0, 159, 160, 5, 37, 0, 0, 160, 38, 1, 0, 0, 0, 161, 162, 5, - 43, 0, 0, 162, 40, 1, 0, 0, 0, 163, 164, 5, 45, 0, 0, 164, 42, 1, 0, 0, - 0, 165, 166, 5, 61, 0, 0, 166, 44, 1, 0, 0, 0, 167, 168, 5, 33, 0, 0, 168, - 169, 5, 61, 0, 0, 169, 46, 1, 0, 0, 0, 170, 171, 5, 62, 0, 0, 171, 48, - 1, 0, 0, 0, 172, 173, 5, 62, 0, 0, 173, 174, 5, 61, 0, 0, 174, 50, 1, 0, - 0, 0, 175, 176, 5, 60, 0, 0, 176, 52, 1, 0, 0, 0, 177, 178, 5, 60, 0, 0, - 178, 179, 5, 62, 0, 0, 179, 54, 1, 0, 0, 0, 180, 181, 5, 60, 0, 0, 181, - 182, 5, 61, 0, 0, 182, 56, 1, 0, 0, 0, 183, 184, 5, 76, 0, 0, 184, 185, - 5, 73, 0, 0, 185, 186, 5, 75, 0, 0, 186, 187, 5, 69, 0, 0, 187, 58, 1, - 0, 0, 0, 188, 189, 5, 69, 0, 0, 189, 190, 5, 88, 0, 0, 190, 191, 5, 73, - 0, 0, 191, 192, 5, 83, 0, 0, 192, 193, 5, 84, 0, 0, 193, 194, 5, 83, 0, - 0, 194, 60, 1, 0, 0, 0, 195, 196, 5, 73, 0, 0, 196, 197, 5, 78, 0, 0, 197, - 62, 1, 0, 0, 0, 198, 199, 5, 84, 0, 0, 199, 200, 5, 82, 0, 0, 200, 201, - 5, 85, 0, 0, 201, 202, 5, 69, 0, 0, 202, 64, 1, 0, 0, 0, 203, 204, 5, 70, - 0, 0, 204, 205, 5, 65, 0, 0, 205, 206, 5, 76, 0, 0, 206, 207, 5, 83, 0, - 0, 207, 208, 5, 69, 0, 0, 208, 66, 1, 0, 0, 0, 209, 210, 3, 5, 2, 0, 210, - 68, 1, 0, 0, 0, 211, 212, 3, 7, 3, 0, 212, 70, 1, 0, 0, 0, 213, 215, 7, - 7, 0, 0, 214, 213, 1, 0, 0, 0, 214, 215, 1, 0, 0, 0, 215, 217, 1, 0, 0, - 0, 216, 218, 3, 9, 4, 0, 217, 216, 1, 0, 0, 0, 218, 219, 1, 0, 0, 0, 219, - 217, 1, 0, 0, 0, 219, 220, 1, 0, 0, 0, 220, 72, 1, 0, 0, 0, 221, 223, 7, - 8, 0, 0, 222, 221, 1, 0, 0, 0, 223, 224, 1, 0, 0, 0, 224, 222, 1, 0, 0, - 0, 224, 225, 1, 0, 0, 0, 225, 74, 1, 0, 0, 0, 226, 228, 7, 1, 0, 0, 227, - 226, 1, 0, 0, 0, 228, 229, 1, 0, 0, 0, 229, 227, 1, 0, 0, 0, 229, 230, - 1, 0, 0, 0, 230, 76, 1, 0, 0, 0, 231, 235, 7, 5, 0, 0, 232, 234, 7, 6, - 0, 0, 233, 232, 1, 0, 0, 0, 234, 237, 1, 0, 0, 0, 235, 233, 1, 0, 0, 0, - 235, 236, 1, 0, 0, 0, 236, 78, 1, 0, 0, 0, 237, 235, 1, 0, 0, 0, 14, 0, - 82, 89, 97, 99, 110, 112, 123, 138, 214, 219, 224, 229, 235, 1, 6, 0, 0, + 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 35, 4, 35, 215, 8, 35, 11, 35, 12, 35, + 216, 1, 36, 4, 36, 220, 8, 36, 11, 36, 12, 36, 221, 1, 37, 4, 37, 225, + 8, 37, 11, 37, 12, 37, 226, 1, 38, 1, 38, 5, 38, 231, 8, 38, 10, 38, 12, + 38, 234, 9, 38, 0, 0, 39, 1, 1, 3, 0, 5, 0, 7, 0, 9, 0, 11, 0, 13, 2, 15, + 3, 17, 4, 19, 5, 21, 6, 23, 0, 25, 7, 27, 8, 29, 9, 31, 10, 33, 11, 35, + 12, 37, 13, 39, 14, 41, 15, 43, 16, 45, 17, 47, 18, 49, 19, 51, 20, 53, + 21, 55, 22, 57, 23, 59, 24, 61, 25, 63, 26, 65, 27, 67, 28, 69, 29, 71, + 30, 73, 31, 75, 32, 77, 33, 1, 0, 8, 3, 0, 9, 10, 13, 13, 32, 32, 3, 0, + 48, 57, 65, 90, 97, 122, 2, 0, 34, 34, 92, 92, 2, 0, 39, 39, 92, 92, 1, + 0, 48, 57, 1, 0, 65, 90, 2, 0, 65, 90, 95, 95, 2, 0, 65, 90, 97, 122, 242, + 0, 1, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, + 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, + 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, + 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, + 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, + 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, + 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, + 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, + 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 1, 80, 1, 0, 0, 0, 3, 87, 1, + 0, 0, 0, 5, 91, 1, 0, 0, 0, 7, 104, 1, 0, 0, 0, 9, 117, 1, 0, 0, 0, 11, + 119, 1, 0, 0, 0, 13, 126, 1, 0, 0, 0, 15, 128, 1, 0, 0, 0, 17, 130, 1, + 0, 0, 0, 19, 132, 1, 0, 0, 0, 21, 134, 1, 0, 0, 0, 23, 138, 1, 0, 0, 0, + 25, 140, 1, 0, 0, 0, 27, 144, 1, 0, 0, 0, 29, 147, 1, 0, 0, 0, 31, 151, + 1, 0, 0, 0, 33, 155, 1, 0, 0, 0, 35, 157, 1, 0, 0, 0, 37, 159, 1, 0, 0, + 0, 39, 161, 1, 0, 0, 0, 41, 163, 1, 0, 0, 0, 43, 165, 1, 0, 0, 0, 45, 167, + 1, 0, 0, 0, 47, 170, 1, 0, 0, 0, 49, 172, 1, 0, 0, 0, 51, 175, 1, 0, 0, + 0, 53, 177, 1, 0, 0, 0, 55, 180, 1, 0, 0, 0, 57, 183, 1, 0, 0, 0, 59, 188, + 1, 0, 0, 0, 61, 195, 1, 0, 0, 0, 63, 198, 1, 0, 0, 0, 65, 203, 1, 0, 0, + 0, 67, 209, 1, 0, 0, 0, 69, 211, 1, 0, 0, 0, 71, 214, 1, 0, 0, 0, 73, 219, + 1, 0, 0, 0, 75, 224, 1, 0, 0, 0, 77, 228, 1, 0, 0, 0, 79, 81, 7, 0, 0, + 0, 80, 79, 1, 0, 0, 0, 81, 82, 1, 0, 0, 0, 82, 80, 1, 0, 0, 0, 82, 83, + 1, 0, 0, 0, 83, 84, 1, 0, 0, 0, 84, 85, 6, 0, 0, 0, 85, 2, 1, 0, 0, 0, + 86, 88, 7, 1, 0, 0, 87, 86, 1, 0, 0, 0, 88, 89, 1, 0, 0, 0, 89, 87, 1, + 0, 0, 0, 89, 90, 1, 0, 0, 0, 90, 4, 1, 0, 0, 0, 91, 99, 5, 34, 0, 0, 92, + 93, 5, 92, 0, 0, 93, 98, 9, 0, 0, 0, 94, 95, 5, 34, 0, 0, 95, 98, 5, 34, + 0, 0, 96, 98, 8, 2, 0, 0, 97, 92, 1, 0, 0, 0, 97, 94, 1, 0, 0, 0, 97, 96, + 1, 0, 0, 0, 98, 101, 1, 0, 0, 0, 99, 97, 1, 0, 0, 0, 99, 100, 1, 0, 0, + 0, 100, 102, 1, 0, 0, 0, 101, 99, 1, 0, 0, 0, 102, 103, 5, 34, 0, 0, 103, + 6, 1, 0, 0, 0, 104, 112, 5, 39, 0, 0, 105, 106, 5, 92, 0, 0, 106, 111, + 9, 0, 0, 0, 107, 108, 5, 39, 0, 0, 108, 111, 5, 39, 0, 0, 109, 111, 8, + 3, 0, 0, 110, 105, 1, 0, 0, 0, 110, 107, 1, 0, 0, 0, 110, 109, 1, 0, 0, + 0, 111, 114, 1, 0, 0, 0, 112, 110, 1, 0, 0, 0, 112, 113, 1, 0, 0, 0, 113, + 115, 1, 0, 0, 0, 114, 112, 1, 0, 0, 0, 115, 116, 5, 39, 0, 0, 116, 8, 1, + 0, 0, 0, 117, 118, 7, 4, 0, 0, 118, 10, 1, 0, 0, 0, 119, 123, 7, 5, 0, + 0, 120, 122, 7, 6, 0, 0, 121, 120, 1, 0, 0, 0, 122, 125, 1, 0, 0, 0, 123, + 121, 1, 0, 0, 0, 123, 124, 1, 0, 0, 0, 124, 12, 1, 0, 0, 0, 125, 123, 1, + 0, 0, 0, 126, 127, 5, 40, 0, 0, 127, 14, 1, 0, 0, 0, 128, 129, 5, 41, 0, + 0, 129, 16, 1, 0, 0, 0, 130, 131, 5, 44, 0, 0, 131, 18, 1, 0, 0, 0, 132, + 133, 5, 39, 0, 0, 133, 20, 1, 0, 0, 0, 134, 135, 5, 34, 0, 0, 135, 22, + 1, 0, 0, 0, 136, 139, 3, 19, 9, 0, 137, 139, 3, 21, 10, 0, 138, 136, 1, + 0, 0, 0, 138, 137, 1, 0, 0, 0, 139, 24, 1, 0, 0, 0, 140, 141, 5, 65, 0, + 0, 141, 142, 5, 78, 0, 0, 142, 143, 5, 68, 0, 0, 143, 26, 1, 0, 0, 0, 144, + 145, 5, 79, 0, 0, 145, 146, 5, 82, 0, 0, 146, 28, 1, 0, 0, 0, 147, 148, + 5, 88, 0, 0, 148, 149, 5, 79, 0, 0, 149, 150, 5, 82, 0, 0, 150, 30, 1, + 0, 0, 0, 151, 152, 5, 78, 0, 0, 152, 153, 5, 79, 0, 0, 153, 154, 5, 84, + 0, 0, 154, 32, 1, 0, 0, 0, 155, 156, 5, 42, 0, 0, 156, 34, 1, 0, 0, 0, + 157, 158, 5, 47, 0, 0, 158, 36, 1, 0, 0, 0, 159, 160, 5, 37, 0, 0, 160, + 38, 1, 0, 0, 0, 161, 162, 5, 43, 0, 0, 162, 40, 1, 0, 0, 0, 163, 164, 5, + 45, 0, 0, 164, 42, 1, 0, 0, 0, 165, 166, 5, 61, 0, 0, 166, 44, 1, 0, 0, + 0, 167, 168, 5, 33, 0, 0, 168, 169, 5, 61, 0, 0, 169, 46, 1, 0, 0, 0, 170, + 171, 5, 62, 0, 0, 171, 48, 1, 0, 0, 0, 172, 173, 5, 62, 0, 0, 173, 174, + 5, 61, 0, 0, 174, 50, 1, 0, 0, 0, 175, 176, 5, 60, 0, 0, 176, 52, 1, 0, + 0, 0, 177, 178, 5, 60, 0, 0, 178, 179, 5, 62, 0, 0, 179, 54, 1, 0, 0, 0, + 180, 181, 5, 60, 0, 0, 181, 182, 5, 61, 0, 0, 182, 56, 1, 0, 0, 0, 183, + 184, 5, 76, 0, 0, 184, 185, 5, 73, 0, 0, 185, 186, 5, 75, 0, 0, 186, 187, + 5, 69, 0, 0, 187, 58, 1, 0, 0, 0, 188, 189, 5, 69, 0, 0, 189, 190, 5, 88, + 0, 0, 190, 191, 5, 73, 0, 0, 191, 192, 5, 83, 0, 0, 192, 193, 5, 84, 0, + 0, 193, 194, 5, 83, 0, 0, 194, 60, 1, 0, 0, 0, 195, 196, 5, 73, 0, 0, 196, + 197, 5, 78, 0, 0, 197, 62, 1, 0, 0, 0, 198, 199, 5, 84, 0, 0, 199, 200, + 5, 82, 0, 0, 200, 201, 5, 85, 0, 0, 201, 202, 5, 69, 0, 0, 202, 64, 1, + 0, 0, 0, 203, 204, 5, 70, 0, 0, 204, 205, 5, 65, 0, 0, 205, 206, 5, 76, + 0, 0, 206, 207, 5, 83, 0, 0, 207, 208, 5, 69, 0, 0, 208, 66, 1, 0, 0, 0, + 209, 210, 3, 5, 2, 0, 210, 68, 1, 0, 0, 0, 211, 212, 3, 7, 3, 0, 212, 70, + 1, 0, 0, 0, 213, 215, 3, 9, 4, 0, 214, 213, 1, 0, 0, 0, 215, 216, 1, 0, + 0, 0, 216, 214, 1, 0, 0, 0, 216, 217, 1, 0, 0, 0, 217, 72, 1, 0, 0, 0, + 218, 220, 7, 7, 0, 0, 219, 218, 1, 0, 0, 0, 220, 221, 1, 0, 0, 0, 221, + 219, 1, 0, 0, 0, 221, 222, 1, 0, 0, 0, 222, 74, 1, 0, 0, 0, 223, 225, 7, + 1, 0, 0, 224, 223, 1, 0, 0, 0, 225, 226, 1, 0, 0, 0, 226, 224, 1, 0, 0, + 0, 226, 227, 1, 0, 0, 0, 227, 76, 1, 0, 0, 0, 228, 232, 7, 5, 0, 0, 229, + 231, 7, 6, 0, 0, 230, 229, 1, 0, 0, 0, 231, 234, 1, 0, 0, 0, 232, 230, + 1, 0, 0, 0, 232, 233, 1, 0, 0, 0, 233, 78, 1, 0, 0, 0, 234, 232, 1, 0, + 0, 0, 13, 0, 82, 89, 97, 99, 110, 112, 123, 138, 216, 221, 226, 232, 1, + 6, 0, 0, } deserializer := antlr.NewATNDeserializer(nil) staticData.atn = deserializer.Deserialize(staticData.serializedATN) diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/parser/expression_visitor.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/parser/expression_visitor.go index 4fb863ac2a3..8ca5fd07ed4 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/parser/expression_visitor.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/parser/expression_visitor.go @@ -6,7 +6,6 @@ package parser import ( - "fmt" "strconv" "strings" @@ -176,13 +175,9 @@ func (v *expressionVisitor) VisitLikeExpression(ctx *gen.LikeExpressionContext) if patternContext.DQUOTED_STRING_LITERAL() != nil { // Parse double quoted string pattern = dQuotedStringToString(patternContext.DQUOTED_STRING_LITERAL().GetText()) - } else if patternContext.SQUOTED_STRING_LITERAL() != nil { + } else { // Parse single quoted string pattern = sQuotedStringToString(patternContext.SQUOTED_STRING_LITERAL().GetText()) - } else { - // not a string, return an error - v.parsingErrors = append(v.parsingErrors, fmt.Errorf("failed to parse LIKE expression: the pattern was not a string literal")) - return noopExpression{} } likeExpression, err := expression.NewLikeExpression(v.Visit(ctx.Expression()).(cesql.Expression), pattern) diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/parser/parser.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/parser/parser.go index e332da2cc3b..2dacf834be7 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/parser/parser.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/parser/parser.go @@ -6,12 +6,13 @@ package parser import ( + "errors" "fmt" + "strings" "github.com/antlr/antlr4/runtime/Go/antlr" - v2 "github.com/cloudevents/sdk-go/sql/v2" - sqlerrors "github.com/cloudevents/sdk-go/sql/v2/errors" + "github.com/cloudevents/sdk-go/sql/v2" "github.com/cloudevents/sdk-go/sql/v2/gen" ) @@ -38,10 +39,10 @@ func (p *Parser) Parse(input string) (v2.Expression, error) { result := antlrParser.Cesql().Accept(&visitor) if result == nil { - return nil, sqlerrors.NewParseError(append(collectingErrorListener.errs, visitor.parsingErrors...)) + return nil, mergeErrs(append(collectingErrorListener.errs, visitor.parsingErrors...)) } - return result.(v2.Expression), sqlerrors.NewParseError(append(collectingErrorListener.errs, visitor.parsingErrors...)) + return result.(v2.Expression), mergeErrs(append(collectingErrorListener.errs, visitor.parsingErrors...)) } type errorListener struct { @@ -53,6 +54,19 @@ func (d *errorListener) SyntaxError(recognizer antlr.Recognizer, offendingSymbol d.errs = append(d.errs, fmt.Errorf("syntax error: %v", e.GetMessage())) } +func mergeErrs(errs []error) error { + if len(errs) == 0 { + return nil + } + + var errStrings []string + for _, err := range errs { + errStrings = append(errStrings, err.Error()) + } + + return errors.New(strings.Join(errStrings, ",")) +} + var defaultParser = Parser{} func Parse(input string) (v2.Expression, error) { diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/runtime/functions_resolver.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/runtime/functions_resolver.go index 5ab964fb7ff..b801368426b 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/runtime/functions_resolver.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/runtime/functions_resolver.go @@ -58,11 +58,6 @@ func (table functionTable) AddFunction(function cesql.Function) error { } } -// Adds user defined function -func AddFunction(fn cesql.Function) error { - return globalFunctionTable.AddFunction(fn) -} - func (table functionTable) ResolveFunction(name string, args int) cesql.Function { item := table[strings.ToUpper(name)] if item == nil { diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/types.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/types.go index 629b7a18d55..0c1f20078e8 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/types.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/types.go @@ -34,21 +34,6 @@ func (t Type) String() string { return "Any" } -func (t Type) ZeroValue() interface{} { - switch t { - case StringType: - return "" - case IntegerType: - return 0 - case BooleanType: - return false - case AnyType: - // by default, return false - return false - } - return false -} - func TypeFromVal(val interface{}) Type { switch val.(type) { case string: diff --git a/vendor/github.com/cloudevents/sdk-go/sql/v2/utils/casting.go b/vendor/github.com/cloudevents/sdk-go/sql/v2/utils/casting.go index d8053adb328..25895374db2 100644 --- a/vendor/github.com/cloudevents/sdk-go/sql/v2/utils/casting.go +++ b/vendor/github.com/cloudevents/sdk-go/sql/v2/utils/casting.go @@ -11,7 +11,6 @@ import ( "strings" cesql "github.com/cloudevents/sdk-go/sql/v2" - sqlerrors "github.com/cloudevents/sdk-go/sql/v2/errors" ) func Cast(val interface{}, target cesql.Type) (interface{}, error) { @@ -37,16 +36,11 @@ func Cast(val interface{}, target cesql.Type) (interface{}, error) { case string: v, err := strconv.ParseInt(val.(string), 10, 32) if err != nil { - err = sqlerrors.NewCastError(fmt.Errorf("cannot cast from String to Integer: %w", err)) + err = fmt.Errorf("cannot cast from String to Integer: %w", err) } return int32(v), err - case bool: - if val.(bool) { - return int32(1), nil - } - return int32(0), nil } - return 0, sqlerrors.NewCastError(fmt.Errorf("undefined cast from %v to %v", cesql.TypeFromVal(val), target)) + return 0, fmt.Errorf("undefined cast from %v to %v", cesql.TypeFromVal(val), target) case cesql.BooleanType: switch val.(type) { case string: @@ -56,14 +50,9 @@ func Cast(val interface{}, target cesql.Type) (interface{}, error) { } else if lowerCase == "false" { return false, nil } - return false, sqlerrors.NewCastError(fmt.Errorf("cannot cast String to Boolean, actual value: %v", val)) - case int32: - if val.(int32) == 0 { - return false, nil - } - return true, nil + return false, fmt.Errorf("cannot cast String to Boolean, actual value: %v", val) } - return false, sqlerrors.NewCastError(fmt.Errorf("undefined cast from %v to %v", cesql.TypeFromVal(val), target)) + return false, fmt.Errorf("undefined cast from %v to %v", cesql.TypeFromVal(val), target) } // AnyType doesn't need casting diff --git a/vendor/github.com/cloudevents/sdk-go/v2/alias.go b/vendor/github.com/cloudevents/sdk-go/v2/alias.go index 2fbfaa9a78f..0f484b33bc4 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/alias.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/alias.go @@ -173,6 +173,7 @@ var ( WithTarget = http.WithTarget WithHeader = http.WithHeader + WithHost = http.WithHost WithShutdownTimeout = http.WithShutdownTimeout //WithEncoding = http.WithEncoding //WithStructuredEncoding = http.WithStructuredEncoding // TODO: expose new way diff --git a/vendor/github.com/cloudevents/sdk-go/v2/binding/buffering/copy_message.go b/vendor/github.com/cloudevents/sdk-go/v2/binding/buffering/copy_message.go index c704bb2aae7..90dc29ad6ff 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/binding/buffering/copy_message.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/binding/buffering/copy_message.go @@ -44,11 +44,12 @@ func CopyMessage(ctx context.Context, m binding.Message, transformers ...binding bm := binaryBufferedMessage{} encoding, err := binding.DirectWrite(ctx, m, &sm, &bm, transformers...) - if encoding == binding.EncodingStructured { + switch encoding { + case binding.EncodingStructured: return &sm, err - } else if encoding == binding.EncodingBinary { + case binding.EncodingBinary: return &bm, err - } else { + default: e, err := binding.ToEvent(ctx, m, transformers...) if err != nil { return nil, err diff --git a/vendor/github.com/cloudevents/sdk-go/v2/binding/test/transformer.go b/vendor/github.com/cloudevents/sdk-go/v2/binding/test/transformer.go index 325b114a43f..13b0aaa70ee 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/binding/test/transformer.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/binding/test/transformer.go @@ -45,15 +45,17 @@ func RunTransformerTests(t *testing.T, ctx context.Context, tests []TransformerT require.NoError(t, err) var e *event.Event - if enc == binding.EncodingStructured { + switch enc { + case binding.EncodingStructured: e, err = binding.ToEvent(ctx, &mockStructured) require.NoError(t, err) - } else if enc == binding.EncodingBinary { + case binding.EncodingBinary: e, err = binding.ToEvent(ctx, &mockBinary) require.NoError(t, err) - } else { + default: t.Fatalf("Unexpected encoding %v", enc) } + require.NoError(t, err) if tt.AssertFunc != nil { tt.AssertFunc(t, *e) diff --git a/vendor/github.com/cloudevents/sdk-go/v2/client/client.go b/vendor/github.com/cloudevents/sdk-go/v2/client/client.go index 452304ffdf9..80051b95cd2 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/client/client.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/client/client.go @@ -38,15 +38,18 @@ type Client interface { // * func() // * func() error // * func(context.Context) - // * func(context.Context) protocol.Result + // * func(context.Context) error // * func(event.Event) - // * func(event.Event) protocol.Result + // * func(event.Event) error // * func(context.Context, event.Event) - // * func(context.Context, event.Event) protocol.Result + // * func(context.Context, event.Event) error // * func(event.Event) *event.Event - // * func(event.Event) (*event.Event, protocol.Result) + // * func(event.Event) (*event.Event, error) // * func(context.Context, event.Event) *event.Event - // * func(context.Context, event.Event) (*event.Event, protocol.Result) + // * func(context.Context, event.Event) (*event.Event, error) + // The error returned may impact the messages processing made by the protocol + // used (example: message acknowledgement). Please refer to each protocol's + // package documentation of the function "Finish(err error) error". StartReceiver(ctx context.Context, fn interface{}) error } diff --git a/vendor/github.com/cloudevents/sdk-go/v2/event/datacodec/codec.go b/vendor/github.com/cloudevents/sdk-go/v2/event/datacodec/codec.go index 3e077740b56..6f5d1f4c583 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/event/datacodec/codec.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/event/datacodec/codec.go @@ -8,6 +8,7 @@ package datacodec import ( "context" "fmt" + "strings" "github.com/cloudevents/sdk-go/v2/event/datacodec/json" "github.com/cloudevents/sdk-go/v2/event/datacodec/text" @@ -26,9 +27,20 @@ type Encoder func(ctx context.Context, in interface{}) ([]byte, error) var decoder map[string]Decoder var encoder map[string]Encoder +// ssDecoder is a map of content-type structured suffixes as defined in +// [Structured Syntax Suffixes](https://www.iana.org/assignments/media-type-structured-suffix/media-type-structured-suffix.xhtml), +// which may be used to match content types such as application/vnd.custom-app+json +var ssDecoder map[string]Decoder + +// ssEncoder is a map of content-type structured suffixes similar to ssDecoder. +var ssEncoder map[string]Encoder + func init() { decoder = make(map[string]Decoder, 10) + ssDecoder = make(map[string]Decoder, 10) + encoder = make(map[string]Encoder, 10) + ssEncoder = make(map[string]Encoder, 10) AddDecoder("", json.Decode) AddDecoder("application/json", json.Decode) @@ -37,12 +49,18 @@ func init() { AddDecoder("text/xml", xml.Decode) AddDecoder("text/plain", text.Decode) + AddStructuredSuffixDecoder("json", json.Decode) + AddStructuredSuffixDecoder("xml", xml.Decode) + AddEncoder("", json.Encode) AddEncoder("application/json", json.Encode) AddEncoder("text/json", json.Encode) AddEncoder("application/xml", xml.Encode) AddEncoder("text/xml", xml.Encode) AddEncoder("text/plain", text.Encode) + + AddStructuredSuffixEncoder("json", json.Encode) + AddStructuredSuffixEncoder("xml", xml.Encode) } // AddDecoder registers a decoder for a given content type. The codecs will use @@ -51,12 +69,34 @@ func AddDecoder(contentType string, fn Decoder) { decoder[contentType] = fn } +// AddStructuredSuffixDecoder registers a decoder for content-types which match the given structured +// syntax suffix as defined by +// [Structured Syntax Suffixes](https://www.iana.org/assignments/media-type-structured-suffix/media-type-structured-suffix.xhtml). +// This allows users to register custom decoders for non-standard content types which follow the +// structured syntax suffix standard (e.g. application/vnd.custom-app+json). +// +// Suffix should not include the "+" character, and "json" and "xml" are registered by default. +func AddStructuredSuffixDecoder(suffix string, fn Decoder) { + ssDecoder[suffix] = fn +} + // AddEncoder registers an encoder for a given content type. The codecs will // use these to encode the data payload for a cloudevent.Event object. func AddEncoder(contentType string, fn Encoder) { encoder[contentType] = fn } +// AddStructuredSuffixEncoder registers an encoder for content-types which match the given +// structured syntax suffix as defined by +// [Structured Syntax Suffixes](https://www.iana.org/assignments/media-type-structured-suffix/media-type-structured-suffix.xhtml). +// This allows users to register custom encoders for non-standard content types which follow the +// structured syntax suffix standard (e.g. application/vnd.custom-app+json). +// +// Suffix should not include the "+" character, and "json" and "xml" are registered by default. +func AddStructuredSuffixEncoder(suffix string, fn Encoder) { + ssEncoder[suffix] = fn +} + // Decode looks up and invokes the decoder registered for the given content // type. An error is returned if no decoder is registered for the given // content type. @@ -64,6 +104,11 @@ func Decode(ctx context.Context, contentType string, in []byte, out interface{}) if fn, ok := decoder[contentType]; ok { return fn(ctx, in, out) } + + if fn, ok := ssDecoder[structuredSuffix(contentType)]; ok { + return fn(ctx, in, out) + } + return fmt.Errorf("[decode] unsupported content type: %q", contentType) } @@ -74,5 +119,19 @@ func Encode(ctx context.Context, contentType string, in interface{}) ([]byte, er if fn, ok := encoder[contentType]; ok { return fn(ctx, in) } + + if fn, ok := ssEncoder[structuredSuffix(contentType)]; ok { + return fn(ctx, in) + } + return nil, fmt.Errorf("[encode] unsupported content type: %q", contentType) } + +func structuredSuffix(contentType string) string { + parts := strings.Split(contentType, "+") + if len(parts) >= 2 { + return parts[len(parts)-1] + } + + return "" +} diff --git a/vendor/github.com/cloudevents/sdk-go/v2/event/event_marshal.go b/vendor/github.com/cloudevents/sdk-go/v2/event/event_marshal.go index c5f2dc03c7d..4e072bdd4d1 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/event/event_marshal.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/event/event_marshal.go @@ -10,6 +10,7 @@ import ( "encoding/base64" "fmt" "io" + "slices" "strings" jsoniter "github.com/json-iterator/go" @@ -179,10 +180,16 @@ func WriteJson(in *Event, writer io.Writer) error { return fmt.Errorf("error while writing the event data: %w", stream.Error) } - for k, v := range ext { + // Add extensions in a deterministic predictable order, similar to how Go maps are serialized in a predictable order. + extensionNames := make([]string, 0, len(ext)) + for extName := range ext { + extensionNames = append(extensionNames, extName) + } + slices.Sort(extensionNames) + for _, extName := range extensionNames { stream.WriteMore() - stream.WriteObjectField(k) - stream.WriteVal(v) + stream.WriteObjectField(extName) + stream.WriteVal(ext[extName]) } stream.WriteObjectEnd() diff --git a/vendor/github.com/cloudevents/sdk-go/v2/event/event_unmarshal.go b/vendor/github.com/cloudevents/sdk-go/v2/event/event_unmarshal.go index 0dd88ae5a77..676dfc95a38 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/event/event_unmarshal.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/event/event_unmarshal.go @@ -7,6 +7,7 @@ package event import ( "encoding/base64" + "encoding/json" "errors" "fmt" "io" @@ -385,9 +386,14 @@ func consumeData(e *Event, isBase64 bool, iter *jsoniter.Iterator) error { e.DataBase64 = true // Allocate payload byte buffer - base64Encoded := iter.ReadStringAsSlice() - e.DataEncoded = make([]byte, base64.StdEncoding.DecodedLen(len(base64Encoded))) - length, err := base64.StdEncoding.Decode(e.DataEncoded, base64Encoded) + base64Encoded := iter.ReadString() + var base64DeJSON string + err := json.Unmarshal([]byte(`"`+base64Encoded+`"`), &base64DeJSON) + if err != nil { + return err + } + e.DataEncoded = make([]byte, base64.StdEncoding.DecodedLen(len(base64DeJSON))) + length, err := base64.StdEncoding.Decode(e.DataEncoded, []byte(base64DeJSON)) if err != nil { return err } diff --git a/vendor/github.com/cloudevents/sdk-go/v2/event/eventcontext_v03.go b/vendor/github.com/cloudevents/sdk-go/v2/event/eventcontext_v03.go index 3f0505547c1..fc67521a28a 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/event/eventcontext_v03.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/event/eventcontext_v03.go @@ -314,7 +314,7 @@ func (ec EventContextV03) String() string { b.WriteString(" datacontentencoding: " + *ec.DataContentEncoding + "\n") } - if ec.Extensions != nil && len(ec.Extensions) > 0 { + if len(ec.Extensions) > 0 { b.WriteString("Extensions,\n") keys := make([]string, 0, len(ec.Extensions)) for k := range ec.Extensions { diff --git a/vendor/github.com/cloudevents/sdk-go/v2/event/eventcontext_v1.go b/vendor/github.com/cloudevents/sdk-go/v2/event/eventcontext_v1.go index 8f164502b05..df311657f70 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/event/eventcontext_v1.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/event/eventcontext_v1.go @@ -299,7 +299,7 @@ func (ec EventContextV1) String() string { b.WriteString(" datacontenttype: " + *ec.DataContentType + "\n") } - if ec.Extensions != nil && len(ec.Extensions) > 0 { + if len(ec.Extensions) > 0 { b.WriteString("Extensions,\n") keys := make([]string, 0, len(ec.Extensions)) for k := range ec.Extensions { diff --git a/vendor/github.com/cloudevents/sdk-go/v2/event/extensions.go b/vendor/github.com/cloudevents/sdk-go/v2/event/extensions.go index 72d0e757aa8..87e5de5726d 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/event/extensions.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/event/extensions.go @@ -49,7 +49,7 @@ func validateExtensionName(key string) error { } for _, c := range key { - if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) { + if (c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9') { return errors.New("bad key, CloudEvents attribute names MUST consist of lower-case letters ('a' to 'z'), upper-case letters ('A' to 'Z') or digits ('0' to '9') from the ASCII character set") } } diff --git a/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/options.go b/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/options.go index 6582af3eafc..91a45ce36c1 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/options.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/options.go @@ -72,6 +72,26 @@ func WithHeader(key, value string) Option { } } +// WithHost sets the outbound host header for all cloud events when using an HTTP request +func WithHost(value string) Option { + return func(p *Protocol) error { + if p == nil { + return fmt.Errorf("http host option can not set nil protocol") + } + value = strings.TrimSpace(value) + if value != "" { + if p.RequestTemplate == nil { + p.RequestTemplate = &nethttp.Request{ + Method: nethttp.MethodPost, + } + } + p.RequestTemplate.Host = value + return nil + } + return fmt.Errorf("http host option was empty string") + } +} + // WithShutdownTimeout sets the shutdown timeout when the http server is being shutdown. func WithShutdownTimeout(timeout time.Duration) Option { return func(p *Protocol) error { @@ -83,6 +103,38 @@ func WithShutdownTimeout(timeout time.Duration) Option { } } +// WithReadTimeout overwrites the default read timeout (600s) of the http +// server. The specified timeout must not be negative. A timeout of 0 disables +// read timeouts in the http server. +func WithReadTimeout(timeout time.Duration) Option { + return func(p *Protocol) error { + if p == nil { + return fmt.Errorf("http read timeout option can not set nil protocol") + } + if timeout < 0 { + return fmt.Errorf("http read timeout must not be negative") + } + p.readTimeout = &timeout + return nil + } +} + +// WithWriteTimeout overwrites the default write timeout (600s) of the http +// server. The specified timeout must not be negative. A timeout of 0 disables +// write timeouts in the http server. +func WithWriteTimeout(timeout time.Duration) Option { + return func(p *Protocol) error { + if p == nil { + return fmt.Errorf("http write timeout option can not set nil protocol") + } + if timeout < 0 { + return fmt.Errorf("http write timeout must not be negative") + } + p.writeTimeout = &timeout + return nil + } +} + func checkListen(p *Protocol, prefix string) error { switch { case p.listener.Load() != nil: diff --git a/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/protocol.go b/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/protocol.go index 7ee3b8fe122..ed76c7dc50d 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/protocol.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/protocol.go @@ -70,6 +70,18 @@ type Protocol struct { // If 0, DefaultShutdownTimeout is used. ShutdownTimeout time.Duration + // readTimeout defines the http.Server ReadTimeout It is the maximum duration + // for reading the entire request, including the body. If not overwritten by an + // option, the default value (600s) is used + readTimeout *time.Duration + + // writeTimeout defines the http.Server WriteTimeout It is the maximum duration + // before timing out writes of the response. It is reset whenever a new + // request's header is read. Like ReadTimeout, it does not let Handlers make + // decisions on a per-request basis. If not overwritten by an option, the + // default value (600s) is used + writeTimeout *time.Duration + // Port is the port configured to bind the receiver to. Defaults to 8080. // If you want to know the effective port you're listening to, use GetListeningPort() Port int @@ -116,6 +128,17 @@ func New(opts ...Option) (*Protocol, error) { p.ShutdownTimeout = DefaultShutdownTimeout } + // use default timeout from abuse protection value + defaultTimeout := DefaultTimeout + + if p.readTimeout == nil { + p.readTimeout = &defaultTimeout + } + + if p.writeTimeout == nil { + p.writeTimeout = &defaultTimeout + } + if p.isRetriableFunc == nil { p.isRetriableFunc = defaultIsRetriableFunc } @@ -303,7 +326,7 @@ func (p *Protocol) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if !ok { rw.Header().Add("Retry-After", strconv.Itoa(int(reset))) - http.Error(rw, "limit exceeded", 429) + http.Error(rw, "limit exceeded", http.StatusTooManyRequests) return } diff --git a/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/protocol_lifecycle.go b/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/protocol_lifecycle.go index 04ef96915a2..7551c31c543 100644 --- a/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/protocol_lifecycle.go +++ b/vendor/github.com/cloudevents/sdk-go/v2/protocol/http/protocol_lifecycle.go @@ -40,8 +40,8 @@ func (p *Protocol) OpenInbound(ctx context.Context) error { p.server = &http.Server{ Addr: listener.Addr().String(), Handler: attachMiddleware(p.Handler, p.middleware), - ReadTimeout: DefaultTimeout, - WriteTimeout: DefaultTimeout, + ReadTimeout: *p.readTimeout, + WriteTimeout: *p.writeTimeout, } // Shutdown diff --git a/vendor/github.com/coreos/go-oidc/v3/oidc/jose.go b/vendor/github.com/coreos/go-oidc/v3/oidc/jose.go index b7bd09275df..f42d37d4812 100644 --- a/vendor/github.com/coreos/go-oidc/v3/oidc/jose.go +++ b/vendor/github.com/coreos/go-oidc/v3/oidc/jose.go @@ -1,5 +1,7 @@ package oidc +import jose "github.com/go-jose/go-jose/v4" + // JOSE asymmetric signing algorithm values as defined by RFC 7518 // // see: https://tools.ietf.org/html/rfc7518#section-3.1 @@ -15,3 +17,16 @@ const ( PS512 = "PS512" // RSASSA-PSS using SHA512 and MGF1-SHA512 EdDSA = "EdDSA" // Ed25519 using SHA-512 ) + +var allAlgs = []jose.SignatureAlgorithm{ + jose.RS256, + jose.RS384, + jose.RS512, + jose.ES256, + jose.ES384, + jose.ES512, + jose.PS256, + jose.PS384, + jose.PS512, + jose.EdDSA, +} diff --git a/vendor/github.com/coreos/go-oidc/v3/oidc/jwks.go b/vendor/github.com/coreos/go-oidc/v3/oidc/jwks.go index b1e3f7e3ff5..6a846ece95b 100644 --- a/vendor/github.com/coreos/go-oidc/v3/oidc/jwks.go +++ b/vendor/github.com/coreos/go-oidc/v3/oidc/jwks.go @@ -13,7 +13,7 @@ import ( "sync" "time" - jose "github.com/go-jose/go-jose/v3" + jose "github.com/go-jose/go-jose/v4" ) // StaticKeySet is a verifier that validates JWT against a static set of public keys. @@ -25,7 +25,9 @@ type StaticKeySet struct { // VerifySignature compares the signature against a static set of public keys. func (s *StaticKeySet) VerifySignature(ctx context.Context, jwt string) ([]byte, error) { - jws, err := jose.ParseSigned(jwt) + // Algorithms are already checked by Verifier, so this parse method accepts + // any algorithm. + jws, err := jose.ParseSigned(jwt, allAlgs) if err != nil { return nil, fmt.Errorf("parsing jwt: %v", err) } @@ -62,16 +64,28 @@ func newRemoteKeySet(ctx context.Context, jwksURL string, now func() time.Time) if now == nil { now = time.Now } - return &RemoteKeySet{jwksURL: jwksURL, ctx: ctx, now: now} + return &RemoteKeySet{ + jwksURL: jwksURL, + now: now, + // For historical reasons, this package uses contexts for configuration, not just + // cancellation. In hindsight, this was a bad idea. + // + // Attemps to reason about how cancels should work with background requests have + // largely lead to confusion. Use the context here as a config bag-of-values and + // ignore the cancel function. + ctx: context.WithoutCancel(ctx), + } } // RemoteKeySet is a KeySet implementation that validates JSON web tokens against // a jwks_uri endpoint. type RemoteKeySet struct { jwksURL string - ctx context.Context now func() time.Time + // Used for configuration. Cancelation is ignored. + ctx context.Context + // guard all other fields mu sync.RWMutex @@ -127,8 +141,13 @@ var parsedJWTKey contextKey func (r *RemoteKeySet) VerifySignature(ctx context.Context, jwt string) ([]byte, error) { jws, ok := ctx.Value(parsedJWTKey).(*jose.JSONWebSignature) if !ok { + // The algorithm values are already enforced by the Validator, which also sets + // the context value above to pre-parsed signature. + // + // Practically, this codepath isn't called in normal use of this package, but + // if it is, the algorithms have already been checked. var err error - jws, err = jose.ParseSigned(jwt) + jws, err = jose.ParseSigned(jwt, allAlgs) if err != nil { return nil, fmt.Errorf("oidc: malformed jwt: %v", err) } diff --git a/vendor/github.com/coreos/go-oidc/v3/oidc/oidc.go b/vendor/github.com/coreos/go-oidc/v3/oidc/oidc.go index b7db3c73429..f6a7ea8a580 100644 --- a/vendor/github.com/coreos/go-oidc/v3/oidc/oidc.go +++ b/vendor/github.com/coreos/go-oidc/v3/oidc/oidc.go @@ -79,7 +79,7 @@ func getClient(ctx context.Context) *http.Client { // provider, err := oidc.NewProvider(ctx, discoveryBaseURL) // // This is insecure because validating the correct issuer is critical for multi-tenant -// proivders. Any overrides here MUST be carefully reviewed. +// providers. Any overrides here MUST be carefully reviewed. func InsecureIssuerURLContext(ctx context.Context, issuerURL string) context.Context { return context.WithValue(ctx, issuerURLKey, issuerURL) } @@ -154,40 +154,65 @@ var supportedAlgorithms = map[string]bool{ EdDSA: true, } -// ProviderConfig allows creating providers when discovery isn't supported. It's -// generally easier to use NewProvider directly. +// ProviderConfig allows direct creation of a [Provider] from metadata +// configuration. This is intended for interop with providers that don't support +// discovery, or host the JSON discovery document at an off-spec path. +// +// The ProviderConfig struct specifies JSON struct tags to support document +// parsing. +// +// // Directly fetch the metadata document. +// resp, err := http.Get("https://login.example.com/custom-metadata-path") +// if err != nil { +// // ... +// } +// defer resp.Body.Close() +// +// // Parse config from JSON metadata. +// config := &oidc.ProviderConfig{} +// if err := json.NewDecoder(resp.Body).Decode(config); err != nil { +// // ... +// } +// p := config.NewProvider(context.Background()) +// +// For providers that implement discovery, use [NewProvider] instead. +// +// See: https://openid.net/specs/openid-connect-discovery-1_0.html type ProviderConfig struct { // IssuerURL is the identity of the provider, and the string it uses to sign // ID tokens with. For example "https://accounts.google.com". This value MUST // match ID tokens exactly. - IssuerURL string + IssuerURL string `json:"issuer"` // AuthURL is the endpoint used by the provider to support the OAuth 2.0 // authorization endpoint. - AuthURL string + AuthURL string `json:"authorization_endpoint"` // TokenURL is the endpoint used by the provider to support the OAuth 2.0 // token endpoint. - TokenURL string + TokenURL string `json:"token_endpoint"` // DeviceAuthURL is the endpoint used by the provider to support the OAuth 2.0 // device authorization endpoint. - DeviceAuthURL string + DeviceAuthURL string `json:"device_authorization_endpoint"` // UserInfoURL is the endpoint used by the provider to support the OpenID // Connect UserInfo flow. // // https://openid.net/specs/openid-connect-core-1_0.html#UserInfo - UserInfoURL string + UserInfoURL string `json:"userinfo_endpoint"` // JWKSURL is the endpoint used by the provider to advertise public keys to // verify issued ID tokens. This endpoint is polled as new keys are made // available. - JWKSURL string + JWKSURL string `json:"jwks_uri"` // Algorithms, if provided, indicate a list of JWT algorithms allowed to sign // ID tokens. If not provided, this defaults to the algorithms advertised by // the JWK endpoint, then the set of algorithms supported by this package. - Algorithms []string + Algorithms []string `json:"id_token_signing_alg_values_supported"` } // NewProvider initializes a provider from a set of endpoints, rather than // through discovery. +// +// The provided context is only used for [http.Client] configuration through +// [ClientContext], not cancelation. func (p *ProviderConfig) NewProvider(ctx context.Context) *Provider { return &Provider{ issuer: p.IssuerURL, @@ -202,9 +227,14 @@ func (p *ProviderConfig) NewProvider(ctx context.Context) *Provider { } // NewProvider uses the OpenID Connect discovery mechanism to construct a Provider. -// // The issuer is the URL identifier for the service. For example: "https://accounts.google.com" // or "https://login.salesforce.com". +// +// OpenID Connect providers that don't implement discovery or host the discovery +// document at a non-spec complaint path (such as requiring a URL parameter), +// should use [ProviderConfig] instead. +// +// See: https://openid.net/specs/openid-connect-discovery-1_0.html func NewProvider(ctx context.Context, issuer string) (*Provider, error) { wellKnown := strings.TrimSuffix(issuer, "/") + "/.well-known/openid-configuration" req, err := http.NewRequest("GET", wellKnown, nil) diff --git a/vendor/github.com/coreos/go-oidc/v3/oidc/verify.go b/vendor/github.com/coreos/go-oidc/v3/oidc/verify.go index 0bca49a8992..52b27b746a2 100644 --- a/vendor/github.com/coreos/go-oidc/v3/oidc/verify.go +++ b/vendor/github.com/coreos/go-oidc/v3/oidc/verify.go @@ -12,7 +12,7 @@ import ( "strings" "time" - jose "github.com/go-jose/go-jose/v3" + jose "github.com/go-jose/go-jose/v4" "golang.org/x/oauth2" ) @@ -120,8 +120,8 @@ type Config struct { } // VerifierContext returns an IDTokenVerifier that uses the provider's key set to -// verify JWTs. As opposed to Verifier, the context is used for all requests to -// the upstream JWKs endpoint. +// verify JWTs. As opposed to Verifier, the context is used to configure requests +// to the upstream JWKs endpoint. The provided context's cancellation is ignored. func (p *Provider) VerifierContext(ctx context.Context, config *Config) *IDTokenVerifier { return p.newVerifier(NewRemoteKeySet(ctx, p.jwksURL), config) } @@ -310,7 +310,16 @@ func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDTok return t, nil } - jws, err := jose.ParseSigned(rawIDToken) + var supportedSigAlgs []jose.SignatureAlgorithm + for _, alg := range v.config.SupportedSigningAlgs { + supportedSigAlgs = append(supportedSigAlgs, jose.SignatureAlgorithm(alg)) + } + if len(supportedSigAlgs) == 0 { + // If no algorithms were specified by both the config and discovery, default + // to the one mandatory algorithm "RS256". + supportedSigAlgs = []jose.SignatureAlgorithm{jose.RS256} + } + jws, err := jose.ParseSigned(rawIDToken, supportedSigAlgs) if err != nil { return nil, fmt.Errorf("oidc: malformed jwt: %v", err) } @@ -322,17 +331,7 @@ func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDTok default: return nil, fmt.Errorf("oidc: multiple signatures on id token not supported") } - sig := jws.Signatures[0] - supportedSigAlgs := v.config.SupportedSigningAlgs - if len(supportedSigAlgs) == 0 { - supportedSigAlgs = []string{RS256} - } - - if !contains(supportedSigAlgs, sig.Header.Algorithm) { - return nil, fmt.Errorf("oidc: id token signed with unsupported algorithm, expected %q got %q", supportedSigAlgs, sig.Header.Algorithm) - } - t.sigAlgorithm = sig.Header.Algorithm ctx = context.WithValue(ctx, parsedJWTKey, jws) diff --git a/vendor/github.com/eclipse/paho.golang/LICENSE b/vendor/github.com/eclipse/paho.golang/LICENSE index d3087e4c540..f55c3953911 100644 --- a/vendor/github.com/eclipse/paho.golang/LICENSE +++ b/vendor/github.com/eclipse/paho.golang/LICENSE @@ -1,3 +1,20 @@ +Eclipse Public License - v 2.0 (EPL-2.0) + +This program and the accompanying materials +are made available under the terms of the Eclipse Public License v2.0 +and Eclipse Distribution License v1.0 which accompany this distribution. + +The Eclipse Public License is available at + https://www.eclipse.org/legal/epl-2.0/ +and the Eclipse Distribution License is available at + http://www.eclipse.org/org/documents/edl-v10.php. + +For an explanation of what dual-licensing means to you, see: +https://www.eclipse.org/legal/eplfaq.php#DUALLIC + +**** +The epl-2.0 is copied below in order to pass the pkg.go.dev license check (https://pkg.go.dev/license-policy). +**** Eclipse Public License - v 2.0 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE @@ -261,8 +278,8 @@ No third-party beneficiary rights are created under this Agreement. Exhibit A - Form of Secondary Licenses Notice -"This Source Code may also be made available under the following -Secondary Licenses when the conditions for such availability set forth +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), version(s), and exceptions or additional permissions here}." diff --git a/vendor/github.com/eclipse/paho.golang/packets/auth.go b/vendor/github.com/eclipse/paho.golang/packets/auth.go index 56237e00c43..c97446f6ad7 100644 --- a/vendor/github.com/eclipse/paho.golang/packets/auth.go +++ b/vendor/github.com/eclipse/paho.golang/packets/auth.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package packets import ( diff --git a/vendor/github.com/eclipse/paho.golang/packets/connack.go b/vendor/github.com/eclipse/paho.golang/packets/connack.go index aa171eaba83..493aa29e021 100644 --- a/vendor/github.com/eclipse/paho.golang/packets/connack.go +++ b/vendor/github.com/eclipse/paho.golang/packets/connack.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package packets import ( @@ -43,7 +58,7 @@ func (c *Connack) String() string { return fmt.Sprintf("CONNACK: ReasonCode:%d SessionPresent:%t\nProperties:\n%s", c.ReasonCode, c.SessionPresent, c.Properties) } -//Unpack is the implementation of the interface required function for a packet +// Unpack is the implementation of the interface required function for a packet func (c *Connack) Unpack(r *bytes.Buffer) error { connackFlags, err := r.ReadByte() if err != nil { diff --git a/vendor/github.com/eclipse/paho.golang/packets/connect.go b/vendor/github.com/eclipse/paho.golang/packets/connect.go index 31340f6bdb9..2394e7d0118 100644 --- a/vendor/github.com/eclipse/paho.golang/packets/connect.go +++ b/vendor/github.com/eclipse/paho.golang/packets/connect.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package packets import ( @@ -85,7 +100,7 @@ func (c *Connect) UnpackFlags(b byte) { c.UsernameFlag = 1&(b>>7) > 0 } -//Unpack is the implementation of the interface required function for a packet +// Unpack is the implementation of the interface required function for a packet func (c *Connect) Unpack(r *bytes.Buffer) error { var err error diff --git a/vendor/github.com/eclipse/paho.golang/packets/disconnect.go b/vendor/github.com/eclipse/paho.golang/packets/disconnect.go index 9180207a610..693abfd3eea 100644 --- a/vendor/github.com/eclipse/paho.golang/packets/disconnect.go +++ b/vendor/github.com/eclipse/paho.golang/packets/disconnect.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package packets import ( diff --git a/vendor/github.com/eclipse/paho.golang/packets/packets.go b/vendor/github.com/eclipse/paho.golang/packets/packets.go index 4f023e015e7..48dc5462e22 100644 --- a/vendor/github.com/eclipse/paho.golang/packets/packets.go +++ b/vendor/github.com/eclipse/paho.golang/packets/packets.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package packets import ( diff --git a/vendor/github.com/eclipse/paho.golang/packets/pingreq.go b/vendor/github.com/eclipse/paho.golang/packets/pingreq.go index 27d39ee324e..b6a4c7fa06f 100644 --- a/vendor/github.com/eclipse/paho.golang/packets/pingreq.go +++ b/vendor/github.com/eclipse/paho.golang/packets/pingreq.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package packets import ( diff --git a/vendor/github.com/eclipse/paho.golang/packets/pingresp.go b/vendor/github.com/eclipse/paho.golang/packets/pingresp.go index fcf421a763f..f5210f187ad 100644 --- a/vendor/github.com/eclipse/paho.golang/packets/pingresp.go +++ b/vendor/github.com/eclipse/paho.golang/packets/pingresp.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package packets import ( diff --git a/vendor/github.com/eclipse/paho.golang/packets/properties.go b/vendor/github.com/eclipse/paho.golang/packets/properties.go index 5a74e0561a1..9ddc9bdc73b 100644 --- a/vendor/github.com/eclipse/paho.golang/packets/properties.go +++ b/vendor/github.com/eclipse/paho.golang/packets/properties.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package packets import ( @@ -285,11 +300,6 @@ func (i *Properties) Pack(p byte) []byte { writeUint16(*i.TopicAliasMaximum, &b) } - if i.MaximumQOS != nil { - b.WriteByte(PropMaximumQOS) - b.WriteByte(*i.MaximumQOS) - } - if i.MaximumPacketSize != nil { b.WriteByte(PropMaximumPacketSize) writeUint32(*i.MaximumPacketSize, &b) @@ -297,6 +307,11 @@ func (i *Properties) Pack(p byte) []byte { } if p == CONNACK { + if i.MaximumQOS != nil { + b.WriteByte(PropMaximumQOS) + b.WriteByte(*i.MaximumQOS) + } + if i.AssignedClientID != "" { b.WriteByte(PropAssignedClientID) writeString(i.AssignedClientID, &b) @@ -453,11 +468,6 @@ func (i *Properties) PackBuf(p byte) *bytes.Buffer { writeUint16(*i.TopicAliasMaximum, &b) } - if i.MaximumQOS != nil { - b.WriteByte(PropMaximumQOS) - b.WriteByte(*i.MaximumQOS) - } - if i.MaximumPacketSize != nil { b.WriteByte(PropMaximumPacketSize) writeUint32(*i.MaximumPacketSize, &b) @@ -465,6 +475,11 @@ func (i *Properties) PackBuf(p byte) *bytes.Buffer { } if p == CONNACK { + if i.MaximumQOS != nil { + b.WriteByte(PropMaximumQOS) + b.WriteByte(*i.MaximumQOS) + } + if i.AssignedClientID != "" { b.WriteByte(PropAssignedClientID) writeString(i.AssignedClientID, &b) @@ -792,7 +807,7 @@ var ValidProperties = map[byte]map[byte]struct{}{ PropReasonString: {CONNACK: {}, PUBACK: {}, PUBREC: {}, PUBREL: {}, PUBCOMP: {}, SUBACK: {}, UNSUBACK: {}, DISCONNECT: {}, AUTH: {}}, PropReceiveMaximum: {CONNECT: {}, CONNACK: {}}, PropTopicAliasMaximum: {CONNECT: {}, CONNACK: {}}, - PropMaximumQOS: {CONNECT: {}, CONNACK: {}}, + PropMaximumQOS: {CONNACK: {}}, PropMaximumPacketSize: {CONNECT: {}, CONNACK: {}}, PropUser: {CONNECT: {}, CONNACK: {}, PUBLISH: {}, PUBACK: {}, PUBREC: {}, PUBREL: {}, PUBCOMP: {}, SUBSCRIBE: {}, UNSUBSCRIBE: {}, SUBACK: {}, UNSUBACK: {}, DISCONNECT: {}, AUTH: {}}, } diff --git a/vendor/github.com/eclipse/paho.golang/packets/puback.go b/vendor/github.com/eclipse/paho.golang/packets/puback.go index 67f404ce6a6..57e6f34f7da 100644 --- a/vendor/github.com/eclipse/paho.golang/packets/puback.go +++ b/vendor/github.com/eclipse/paho.golang/packets/puback.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package packets import ( @@ -41,7 +56,7 @@ func (p *Puback) String() string { return b.String() } -//Unpack is the implementation of the interface required function for a packet +// Unpack is the implementation of the interface required function for a packet func (p *Puback) Unpack(r *bytes.Buffer) error { var err error success := r.Len() == 2 diff --git a/vendor/github.com/eclipse/paho.golang/packets/pubcomp.go b/vendor/github.com/eclipse/paho.golang/packets/pubcomp.go index 1cdfe61e98b..b193be03752 100644 --- a/vendor/github.com/eclipse/paho.golang/packets/pubcomp.go +++ b/vendor/github.com/eclipse/paho.golang/packets/pubcomp.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package packets import ( @@ -34,7 +49,7 @@ func (p *Pubcomp) String() string { return b.String() } -//Unpack is the implementation of the interface required function for a packet +// Unpack is the implementation of the interface required function for a packet func (p *Pubcomp) Unpack(r *bytes.Buffer) error { var err error success := r.Len() == 2 diff --git a/vendor/github.com/eclipse/paho.golang/packets/publish.go b/vendor/github.com/eclipse/paho.golang/packets/publish.go index 24edb588b23..150ea3417b0 100644 --- a/vendor/github.com/eclipse/paho.golang/packets/publish.go +++ b/vendor/github.com/eclipse/paho.golang/packets/publish.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package packets import ( diff --git a/vendor/github.com/eclipse/paho.golang/packets/pubrec.go b/vendor/github.com/eclipse/paho.golang/packets/pubrec.go index 7bd30451099..f1627968b5d 100644 --- a/vendor/github.com/eclipse/paho.golang/packets/pubrec.go +++ b/vendor/github.com/eclipse/paho.golang/packets/pubrec.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package packets import ( diff --git a/vendor/github.com/eclipse/paho.golang/packets/pubrel.go b/vendor/github.com/eclipse/paho.golang/packets/pubrel.go index 27c48c24042..1f8ea9447de 100644 --- a/vendor/github.com/eclipse/paho.golang/packets/pubrel.go +++ b/vendor/github.com/eclipse/paho.golang/packets/pubrel.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package packets import ( @@ -28,7 +43,7 @@ func (p *Pubrel) String() string { return b.String() } -//Unpack is the implementation of the interface required function for a packet +// Unpack is the implementation of the interface required function for a packet func (p *Pubrel) Unpack(r *bytes.Buffer) error { var err error success := r.Len() == 2 diff --git a/vendor/github.com/eclipse/paho.golang/packets/suback.go b/vendor/github.com/eclipse/paho.golang/packets/suback.go index 2503aaf1aec..be5eaaa2b06 100644 --- a/vendor/github.com/eclipse/paho.golang/packets/suback.go +++ b/vendor/github.com/eclipse/paho.golang/packets/suback.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package packets import ( @@ -34,7 +49,7 @@ const ( SubackWildcardsubscriptionsnotsupported = 0xA2 ) -//Unpack is the implementation of the interface required function for a packet +// Unpack is the implementation of the interface required function for a packet func (s *Suback) Unpack(r *bytes.Buffer) error { var err error s.PacketID, err = readUint16(r) diff --git a/vendor/github.com/eclipse/paho.golang/packets/subscribe.go b/vendor/github.com/eclipse/paho.golang/packets/subscribe.go index 2abccbbd674..c179e4eb902 100644 --- a/vendor/github.com/eclipse/paho.golang/packets/subscribe.go +++ b/vendor/github.com/eclipse/paho.golang/packets/subscribe.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package packets import ( diff --git a/vendor/github.com/eclipse/paho.golang/packets/unsuback.go b/vendor/github.com/eclipse/paho.golang/packets/unsuback.go index ba5164b9f19..264ebce1d38 100644 --- a/vendor/github.com/eclipse/paho.golang/packets/unsuback.go +++ b/vendor/github.com/eclipse/paho.golang/packets/unsuback.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package packets import ( diff --git a/vendor/github.com/eclipse/paho.golang/packets/unsubscribe.go b/vendor/github.com/eclipse/paho.golang/packets/unsubscribe.go index 090d7ca7209..4af1bc5fd71 100644 --- a/vendor/github.com/eclipse/paho.golang/packets/unsubscribe.go +++ b/vendor/github.com/eclipse/paho.golang/packets/unsubscribe.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package packets import ( diff --git a/vendor/github.com/eclipse/paho.golang/paho/acks_tracker.go b/vendor/github.com/eclipse/paho.golang/paho/acks_tracker.go index 47f11cb67f4..d4077b0eef4 100644 --- a/vendor/github.com/eclipse/paho.golang/paho/acks_tracker.go +++ b/vendor/github.com/eclipse/paho.golang/paho/acks_tracker.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package paho import ( diff --git a/vendor/github.com/eclipse/paho.golang/paho/auth.go b/vendor/github.com/eclipse/paho.golang/paho/auth.go index 7d3a3c97233..3ab6496566c 100644 --- a/vendor/github.com/eclipse/paho.golang/paho/auth.go +++ b/vendor/github.com/eclipse/paho.golang/paho/auth.go @@ -1,8 +1,23 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package paho // Auther is the interface for something that implements the extended authentication // flows in MQTT v5 type Auther interface { - Authenticate(*Auth) *Auth - Authenticated() + Authenticate(*Auth) *Auth // Authenticate will be called when an AUTH packet is received. + Authenticated() // Authenticated will be called when CONNACK is received } diff --git a/vendor/github.com/eclipse/paho.golang/paho/client.go b/vendor/github.com/eclipse/paho.golang/paho/client.go index 76a98722933..d4bea750d0d 100644 --- a/vendor/github.com/eclipse/paho.golang/paho/client.go +++ b/vendor/github.com/eclipse/paho.golang/paho/client.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package paho import ( @@ -11,7 +26,9 @@ import ( "time" "github.com/eclipse/paho.golang/packets" - "golang.org/x/sync/semaphore" + "github.com/eclipse/paho.golang/paho/log" + "github.com/eclipse/paho.golang/paho/session" + "github.com/eclipse/paho.golang/paho/session/state" ) type MQTTVersion byte @@ -25,10 +42,22 @@ const defaultSendAckInterval = 50 * time.Millisecond var ( ErrManualAcknowledgmentDisabled = errors.New("manual acknowledgments disabled") + ErrNetworkErrorAfterStored = errors.New("error after packet added to state") // Could not send packet but its stored (and response will be sent on chan at some point in the future) + ErrConnectionLost = errors.New("connection lost after request transmitted") // We don't know whether the server received the request or not + + ErrInvalidArguments = errors.New("invalid argument") // If included (errors.Join) in an error, there is a problem with the arguments passed. Retrying on the same connection with the same arguments will not succeed. ) type ( - // ClientConfig are the user configurable options for the client, an + PublishReceived struct { + Packet *Publish + Client *Client // The Client that received the message (note that the connection may have been lost post-receipt) + + AlreadyHandled bool // Set to true if a previous callback has returned true (indicating some action has already been taken re the message) + Errs []error // Errors returned by previous handlers (if any). + } + + // ClientConfig are the user-configurable options for the client, an // instance of this struct is passed into NewClient(), not all options // are required to be set, defaults are provided for Persistence, MIDs, // PingHandler, PacketTimeout and Router. @@ -38,12 +67,27 @@ type ( // BEWARE that most wrapped net.Conn implementations like tls.Conn are // not thread safe for writing. To fix, use packets.NewThreadSafeConn // wrapper or extend the custom net.Conn struct with sync.Locker. - Conn net.Conn - MIDs MIDService + Conn net.Conn + + Session session.SessionManager + autoCloseSession bool + AuthHandler Auther PingHandler Pinger - Router Router - Persistence Persistence + defaultPinger bool + + // Router - new inbound messages will be passed to the `Route(*packets.Publish)` function. + // + // Depreciated: If a router is provided, it will now be added to the end of the OnPublishReceived + // slice (which provides a more flexible approach to handling incoming messages). + Router Router + + // OnPublishReceived provides a slice of callbacks; additional handlers may be added after the client has been + // created via the AddOnPublishReceived function (Client holds a copy of the slice; OnPublishReceived will not change). + // When a `PUBLISH` is received, the callbacks will be called in order. If a callback processes the message, + // then it should return true. This boolean, and any errors, will be passed to subsequent handlers. + OnPublishReceived []func(PublishReceived) (bool, error) + PacketTimeout time.Duration // OnServerDisconnect is called only when a packets.DISCONNECT is received from server OnServerDisconnect func(*Disconnect) @@ -68,20 +112,30 @@ type ( } // Client is the struct representing an MQTT client Client struct { - mu sync.Mutex - ClientConfig - // raCtx is used for handling the MQTTv5 authentication exchange. - raCtx *CPContext - stop chan struct{} + config ClientConfig + + // OnPublishReceived copy of OnPublishReceived from ClientConfig (perhaps with added callback form Router) + onPublishReceived []func(PublishReceived) (bool, error) + onPublishReceivedTracker []int // Used to track positions in above + onPublishReceivedMu sync.Mutex + + // authResponse is used for handling the MQTTv5 authentication exchange (MUST be buffered) + authResponse chan<- packets.ControlPacket + authResponseMu sync.Mutex // protects the above + + cancelFunc func() + + connectCalled bool // if true `Connect` has been called and a connection is being managed + connectCalledMu sync.Mutex // protects the above + + done <-chan struct{} // closed when shutdown complete (only valid after Connect returns nil error) publishPackets chan *packets.Publish acksTracker acksTracker workers sync.WaitGroup serverProps CommsProperties clientProps CommsProperties - serverInflight *semaphore.Weighted - clientInflight *semaphore.Weighted - debug Logger - errors Logger + debug log.Logger + errors log.Logger } // CommsProperties is a struct of the communication properties that may @@ -97,11 +151,6 @@ type ( SubIDAvailable bool SharedSubAvailable bool } - - caContext struct { - Context context.Context - Return chan *packets.Connack - } ) // NewClient is used to create a new default instance of an MQTT client. @@ -129,30 +178,40 @@ func NewClient(conf ClientConfig) *Client { MaximumPacketSize: 0, TopicAliasMaximum: 0, }, - ClientConfig: conf, - errors: NOOPLogger{}, - debug: NOOPLogger{}, + config: conf, + onPublishReceived: conf.OnPublishReceived, + done: make(chan struct{}), + errors: log.NOOPLogger{}, + debug: log.NOOPLogger{}, } - if c.Persistence == nil { - c.Persistence = &noopPersistence{} + if c.config.Session == nil { + c.config.Session = state.NewInMemory() + c.config.autoCloseSession = true // We created `Session`, so need to close it when done (so handlers all return) } - if c.MIDs == nil { - c.MIDs = &MIDs{index: make([]*CPContext, int(midMax))} + if c.config.PacketTimeout == 0 { + c.config.PacketTimeout = 10 * time.Second } - if c.PacketTimeout == 0 { - c.PacketTimeout = 10 * time.Second + + if c.config.Router == nil && len(c.onPublishReceived) == 0 { + c.config.Router = NewStandardRouter() // Maintain backwards compatibility (for now!) } - if c.Router == nil { - c.Router = NewStandardRouter() + if c.config.Router != nil { + r := c.config.Router + c.onPublishReceived = append(c.onPublishReceived, + func(p PublishReceived) (bool, error) { + r.Route(p.Packet.Packet()) + return false, nil + }) } - if c.PingHandler == nil { - c.PingHandler = DefaultPingerWithCustomFailHandler(func(e error) { - go c.error(e) - }) + c.onPublishReceivedTracker = make([]int, len(c.onPublishReceived)) // Must have the same number of elements as onPublishReceived + + if c.config.PingHandler == nil { + c.config.PingHandler = NewDefaultPinger() + c.config.defaultPinger = true } - if c.OnClientError == nil { - c.OnClientError = func(e error) {} + if c.config.OnClientError == nil { + c.config.OnClientError = func(e error) {} } return c @@ -162,23 +221,38 @@ func NewClient(conf ClientConfig) *Client { // the Client instance already has a working network connection. // The function takes a pre-prepared Connect packet, and uses that to // establish an MQTT connection. Assuming the connection completes -// successfully the rest of the client is initiated and the Connack -// returned. Otherwise the failure Connack (if there is one) is returned +// successfully, the rest of the client is initiated and the Connack +// returned. Otherwise, the failure Connack (if there is one) is returned // along with an error indicating the reason for the failure to connect. func (c *Client) Connect(ctx context.Context, cp *Connect) (*Connack, error) { - if c.Conn == nil { + if c.config.Conn == nil { return nil, fmt.Errorf("client connection is nil") } + // The connection is in c.config.Conn which is inaccessible to the user. + // The end result of `Connect` (possibly some time after it returns) will be to close the connection so calling + // Connect twice is invalid. + c.connectCalledMu.Lock() + if c.connectCalled { + c.connectCalledMu.Unlock() + return nil, fmt.Errorf("connect must only be called once") + } + c.connectCalled = true + c.connectCalledMu.Unlock() + + // The passed in ctx applies to the connection process only. clientCtx applies to Client (signals that the + // client should shut down). + clientCtx, cancelFunc := context.WithCancel(context.Background()) + done := make(chan struct{}) cleanup := func() { - close(c.stop) + cancelFunc() close(c.publishPackets) - _ = c.Conn.Close() - c.mu.Unlock() + _ = c.config.Conn.Close() + close(done) } - c.mu.Lock() - c.stop = make(chan struct{}) + c.cancelFunc = cancelFunc + c.done = done var publishPacketsSize uint16 = math.MaxUint16 if cp.Properties != nil && cp.Properties.ReceiveMaximum != nil { @@ -187,14 +261,11 @@ func (c *Client) Connect(ctx context.Context, cp *Connect) (*Connack, error) { c.publishPackets = make(chan *packets.Publish, publishPacketsSize) keepalive := cp.KeepAlive - c.ClientID = cp.ClientID + c.config.ClientID = cp.ClientID if cp.Properties != nil { if cp.Properties.MaximumPacketSize != nil { c.clientProps.MaximumPacketSize = *cp.Properties.MaximumPacketSize } - if cp.Properties.MaximumQOS != nil { - c.clientProps.MaximumQoS = *cp.Properties.MaximumQOS - } if cp.Properties.ReceiveMaximum != nil { c.clientProps.ReceiveMaximum = *cp.Properties.ReceiveMaximum } @@ -204,7 +275,7 @@ func (c *Client) Connect(ctx context.Context, cp *Connect) (*Connack, error) { } c.debug.Println("connecting") - connCtx, cf := context.WithTimeout(ctx, c.PacketTimeout) + connCtx, cf := context.WithTimeout(ctx, c.config.PacketTimeout) defer cf() ccp := cp.Packet() @@ -212,14 +283,14 @@ func (c *Client) Connect(ctx context.Context, cp *Connect) (*Connack, error) { ccp.ProtocolVersion = 5 c.debug.Println("sending CONNECT") - if _, err := ccp.WriteTo(c.Conn); err != nil { + if _, err := ccp.WriteTo(c.config.Conn); err != nil { cleanup() return nil, err } c.debug.Println("waiting for CONNACK/AUTH") var ( - caPacket *packets.Connack + caPacket *packets.Connack // We use buffered channels to prevent goroutine leak. The Details are below. // - c.expectConnack waits to send data to caPacketCh or caPacketErr. // - If connCtx is cancelled (done) before c.expectConnack finishes to send data to either "unbuffered" channel, @@ -230,11 +301,10 @@ func (c *Client) Connect(ctx context.Context, cp *Connect) (*Connack, error) { go c.expectConnack(caPacketCh, caPacketErr) select { case <-connCtx.Done(): - if ctxErr := connCtx.Err(); ctxErr != nil { - c.debug.Println(fmt.Sprintf("terminated due to context: %v", ctxErr)) - } + ctxErr := connCtx.Err() + c.debug.Println(fmt.Sprintf("terminated due to context waiting for CONNACK: %v", ctxErr)) cleanup() - return nil, connCtx.Err() + return nil, ctxErr case err := <-caPacketErr: c.debug.Println(err) cleanup() @@ -254,15 +324,21 @@ func (c *Client) Connect(ctx context.Context, cp *Connect) (*Connack, error) { return ca, fmt.Errorf("failed to connect to server: %s", reason) } - // no more possible calls to cleanup(), defer an unlock - defer c.mu.Unlock() + if err := c.config.Session.ConAckReceived(c.config.Conn, ccp, caPacket); err != nil { + cleanup() + return ca, fmt.Errorf("session error: %w", err) + } + + // the connection is now fully up and a nil error will be returned. + // cleanup() must not be called past this point and will be handled by `shutdown` + context.AfterFunc(clientCtx, func() { c.shutdown(done) }) if ca.Properties != nil { if ca.Properties.ServerKeepAlive != nil { keepalive = *ca.Properties.ServerKeepAlive } if ca.Properties.AssignedClientID != "" { - c.ClientID = ca.Properties.AssignedClientID + c.config.ClientID = ca.Properties.AssignedClientID } if ca.Properties.ReceiveMaximum != nil { c.serverProps.ReceiveMaximum = *ca.Properties.ReceiveMaximum @@ -282,15 +358,14 @@ func (c *Client) Connect(ctx context.Context, cp *Connect) (*Connack, error) { c.serverProps.SharedSubAvailable = ca.Properties.SharedSubAvailable } - c.serverInflight = semaphore.NewWeighted(int64(c.serverProps.ReceiveMaximum)) - c.clientInflight = semaphore.NewWeighted(int64(c.clientProps.ReceiveMaximum)) - c.debug.Println("received CONNACK, starting PingHandler") c.workers.Add(1) go func() { defer c.workers.Done() defer c.debug.Println("returning from ping handler worker") - c.PingHandler.Start(c.Conn, time.Duration(keepalive)*time.Second) + if err := c.config.PingHandler.Run(clientCtx, c.config.Conn, keepalive); err != nil { + go c.error(fmt.Errorf("ping handler error: %w", err)) + } }() c.debug.Println("starting publish packets loop") @@ -298,6 +373,8 @@ func (c *Client) Connect(ctx context.Context, cp *Connect) (*Connack, error) { go func() { defer c.workers.Done() defer c.debug.Println("returning from publish packets loop worker") + // exits when `c.publishPackets` is closed (`c.incoming()` closes this). This is important because + // messages may be passed for processing after `c.stop` has been closed. c.routePublishPackets() }() @@ -306,16 +383,16 @@ func (c *Client) Connect(ctx context.Context, cp *Connect) (*Connack, error) { go func() { defer c.workers.Done() defer c.debug.Println("returning from incoming worker") - c.incoming() + c.incoming(clientCtx) }() - if c.EnableManualAcknowledgment { + if c.config.EnableManualAcknowledgment { c.debug.Println("starting acking routine") c.acksTracker.reset() sendAcksInterval := defaultSendAckInterval - if c.SendAcksInterval > 0 { - sendAcksInterval = c.SendAcksInterval + if c.config.SendAcksInterval > 0 { + sendAcksInterval = c.config.SendAcksInterval } c.workers.Add(1) @@ -325,7 +402,7 @@ func (c *Client) Connect(ctx context.Context, cp *Connect) (*Connack, error) { t := time.NewTicker(sendAcksInterval) for { select { - case <-c.stop: + case <-clientCtx.Done(): return case <-t.C: c.acksTracker.flush(func(pbs []*packets.Publish) { @@ -341,8 +418,17 @@ func (c *Client) Connect(ctx context.Context, cp *Connect) (*Connack, error) { return ca, nil } +// Done returns a channel that will be closed when Client has shutdown. Only valid after Connect has returned a +// nil error. +func (c *Client) Done() <-chan struct{} { + return c.done +} + +// Ack transmits an acknowledgement of the `Publish` packet. +// WARNING: Calling Ack after the connection is closed may have unpredictable results (particularly if the sessionState +// is being accessed by a new connection). See issue #160. func (c *Client) Ack(pb *Publish) error { - if !c.EnableManualAcknowledgment { + if !c.config.EnableManualAcknowledgment { return ErrManualAcknowledgmentDisabled } if pb.QoS == 0 { @@ -351,52 +437,45 @@ func (c *Client) Ack(pb *Publish) error { return c.acksTracker.markAsAcked(pb.Packet()) } +// ack acknowledges a message (note: called by acksTracker to ensure these are sent in order) func (c *Client) ack(pb *packets.Publish) { - switch pb.QoS { - case 1: - pa := packets.Puback{ - Properties: &packets.Properties{}, - PacketID: pb.PacketID, - } - c.debug.Println("sending PUBACK") - _, err := pa.WriteTo(c.Conn) - if err != nil { - c.errors.Printf("failed to send PUBACK for %d: %s", pb.PacketID, err) - } - case 2: - pr := packets.Pubrec{ - Properties: &packets.Properties{}, - PacketID: pb.PacketID, - } - c.debug.Printf("sending PUBREC") - _, err := pr.WriteTo(c.Conn) - if err != nil { - c.errors.Printf("failed to send PUBREC for %d: %s", pb.PacketID, err) - } - } + c.config.Session.Ack(pb) } +// routePublishPackets listens on c.publishPackets and passes received messages to the handlers +// terminates when publishPackets closed func (c *Client) routePublishPackets() { - for { - select { - case <-c.stop: - return - case pb, open := <-c.publishPackets: - if !open { - return - } + for pb := range c.publishPackets { + // Copy onPublishReceived so lock is only held briefly + c.onPublishReceivedMu.Lock() + handlers := make([]func(PublishReceived) (bool, error), len(c.onPublishReceived)) + for i := range c.onPublishReceived { + handlers[i] = c.onPublishReceived[i] + } + c.onPublishReceivedMu.Unlock() - if !c.ClientConfig.EnableManualAcknowledgment { - c.Router.Route(pb) - c.ack(pb) - continue - } + if c.config.EnableManualAcknowledgment && pb.QoS != 0 { + c.acksTracker.add(pb) + } - if pb.QoS != 0 { - c.acksTracker.add(pb) + var handled bool + var errs []error + pkt := PublishFromPacketPublish(pb) + for _, h := range handlers { + ha, err := h(PublishReceived{ + Packet: pkt, + Client: c, + AlreadyHandled: handled, + Errs: errs, + }) + if ha { + handled = true } + errs = append(errs, err) + } - c.Router.Route(pb) + if !c.config.EnableManualAcknowledgment { + c.ack(pb) } } } @@ -406,21 +485,24 @@ func (c *Client) routePublishPackets() { // from Connect(), it exits when it receives a server initiated // Disconnect, the Stop channel is closed or there is an error reading // a packet from the network connection -func (c *Client) incoming() { +// Closes `c.publishPackets` when done (should be the only thing sending on this channel) +func (c *Client) incoming(ctx context.Context) { defer c.debug.Println("client stopping, incoming stopping") + defer close(c.publishPackets) + for { select { - case <-c.stop: + case <-ctx.Done(): return default: - recv, err := packets.ReadPacket(c.Conn) + recv, err := packets.ReadPacket(c.config.Conn) if err != nil { go c.error(err) return } switch recv.Type { case packets.CONNACK: - c.debug.Println("received CONNACK") + c.debug.Println("received CONNACK (unexpected)") go c.error(fmt.Errorf("received unexpected CONNACK")) return case packets.AUTH: @@ -428,93 +510,55 @@ func (c *Client) incoming() { ap := recv.Content.(*packets.Auth) switch ap.ReasonCode { case packets.AuthSuccess: - if c.AuthHandler != nil { - go c.AuthHandler.Authenticated() + if c.config.AuthHandler != nil { + go c.config.AuthHandler.Authenticated() } - if c.raCtx != nil { - c.raCtx.Return <- *recv + c.authResponseMu.Lock() + if c.authResponse != nil { + select { // authResponse must be buffered, and we should only receive 1 AUTH packet a time + case c.authResponse <- *recv: + default: + } } + c.authResponseMu.Unlock() case packets.AuthContinueAuthentication: - if c.AuthHandler != nil { - if _, err := c.AuthHandler.Authenticate(AuthFromPacketAuth(ap)).Packet().WriteTo(c.Conn); err != nil { + if c.config.AuthHandler != nil { + if _, err := c.config.AuthHandler.Authenticate(AuthFromPacketAuth(ap)).Packet().WriteTo(c.config.Conn); err != nil { go c.error(err) return } + c.config.PingHandler.PacketSent() } } case packets.PUBLISH: pb := recv.Content.(*packets.Publish) - c.debug.Printf("received QoS%d PUBLISH", pb.QoS) - c.mu.Lock() - select { - case <-c.stop: - c.mu.Unlock() - return - default: - c.publishPackets <- pb - c.mu.Unlock() - } - case packets.PUBACK, packets.PUBCOMP, packets.SUBACK, packets.UNSUBACK: - c.debug.Printf("received %s packet with id %d", recv.PacketType(), recv.PacketID()) - if cpCtx := c.MIDs.Get(recv.PacketID()); cpCtx != nil { - cpCtx.Return <- *recv - } else { - c.debug.Println("received a response for a message ID we don't know:", recv.PacketID()) - } - case packets.PUBREC: - c.debug.Println("received PUBREC for", recv.PacketID()) - if cpCtx := c.MIDs.Get(recv.PacketID()); cpCtx == nil { - c.debug.Println("received a PUBREC for a message ID we don't know:", recv.PacketID()) - pl := packets.Pubrel{ - PacketID: recv.Content.(*packets.Pubrec).PacketID, - ReasonCode: 0x92, - } - c.debug.Println("sending PUBREL for", pl.PacketID) - _, err := pl.WriteTo(c.Conn) - if err != nil { - c.errors.Printf("failed to send PUBREL for %d: %s", pl.PacketID, err) - } - } else { - pr := recv.Content.(*packets.Pubrec) - if pr.ReasonCode >= 0x80 { - //Received a failure code, shortcut and return - cpCtx.Return <- *recv - } else { - pl := packets.Pubrel{ - PacketID: pr.PacketID, - } - c.debug.Println("sending PUBREL for", pl.PacketID) - _, err := pl.WriteTo(c.Conn) - if err != nil { - c.errors.Printf("failed to send PUBREL for %d: %s", pl.PacketID, err) - } - } - } - case packets.PUBREL: - c.debug.Println("received PUBREL for", recv.PacketID()) - //Auto respond to pubrels unless failure code - pr := recv.Content.(*packets.Pubrel) - if pr.ReasonCode >= 0x80 { - //Received a failure code, continue - continue + if pb.QoS > 0 { // QOS1 or 2 need to be recorded in session state + c.config.Session.PacketReceived(recv, c.publishPackets) } else { - pc := packets.Pubcomp{ - PacketID: pr.PacketID, - } - c.debug.Println("sending PUBCOMP for", pr.PacketID) - _, err := pc.WriteTo(c.Conn) - if err != nil { - c.errors.Printf("failed to send PUBCOMP for %d: %s", pc.PacketID, err) + c.debug.Printf("received QoS%d PUBLISH", pb.QoS) + select { + case <-ctx.Done(): + return + case c.publishPackets <- pb: } } + case packets.PUBACK, packets.PUBCOMP, packets.SUBACK, packets.UNSUBACK, packets.PUBREC, packets.PUBREL: + c.config.Session.PacketReceived(recv, c.publishPackets) case packets.DISCONNECT: + pd := recv.Content.(*packets.Disconnect) c.debug.Println("received DISCONNECT") - if c.raCtx != nil { - c.raCtx.Return <- *recv + c.authResponseMu.Lock() + if c.authResponse != nil { + select { // authResponse must be buffered, and we should only receive 1 AUTH packet a time + case c.authResponse <- *recv: + default: + } } + c.authResponseMu.Unlock() + c.config.Session.ConnectionLost(pd) // this may impact the session state go func() { - if c.OnServerDisconnect != nil { - go c.serverDisconnect(DisconnectFromPacketDisconnect(recv.Content.(*packets.Disconnect))) + if c.config.OnServerDisconnect != nil { + go c.serverDisconnect(DisconnectFromPacketDisconnect(pd)) } else { go c.error(fmt.Errorf("server initiated disconnect")) } @@ -522,33 +566,37 @@ func (c *Client) incoming() { return case packets.PINGRESP: c.debug.Println("received PINGRESP") - c.PingHandler.PingResp() + c.config.PingHandler.PingResp() } } } } +// close terminates the connection and waits for a clean shutdown +// may be called multiple times (subsequent calls will wait on previously requested shutdown) func (c *Client) close() { - c.mu.Lock() - defer c.mu.Unlock() - - select { - case <-c.stop: - //already shutting down, do nothing - return - default: - } - - close(c.stop) - close(c.publishPackets) + c.cancelFunc() // cleanup handled by AfterFunc defined in Connect + <-c.done +} - c.debug.Println("client stopped") - c.PingHandler.Stop() - c.debug.Println("ping stopped") - _ = c.Conn.Close() +// shutdown cleanly shutdown the client +// This should only be called via the AfterFunc in `Connect` (shutdown must not be called more than once) +func (c *Client) shutdown(done chan<- struct{}) { + c.debug.Println("client stop requested") + _ = c.config.Conn.Close() c.debug.Println("conn closed") c.acksTracker.reset() c.debug.Println("acks tracker reset") + c.config.Session.ConnectionLost(nil) + if c.config.autoCloseSession { + if err := c.config.Session.Close(); err != nil { + c.errors.Println("error closing session", err) + } + } + c.debug.Println("session updated, waiting on workers") + c.workers.Wait() + c.debug.Println("workers done") + close(done) } // error is called to signify that an error situation has occurred, this @@ -558,15 +606,13 @@ func (c *Client) close() { func (c *Client) error(e error) { c.debug.Println("error called:", e) c.close() - c.workers.Wait() - go c.OnClientError(e) + go c.config.OnClientError(e) } func (c *Client) serverDisconnect(d *Disconnect) { c.close() - c.workers.Wait() c.debug.Println("calling OnServerDisconnect") - go c.OnServerDisconnect(d) + go c.config.OnServerDisconnect(d) } // Authenticate is used to initiate a reauthentication of credentials with the @@ -576,39 +622,39 @@ func (c *Client) serverDisconnect(d *Disconnect) { // is received. func (c *Client) Authenticate(ctx context.Context, a *Auth) (*AuthResponse, error) { c.debug.Println("client initiated reauthentication") - - c.mu.Lock() - if c.raCtx != nil { - c.mu.Unlock() + authResp := make(chan packets.ControlPacket, 1) + c.authResponseMu.Lock() + if c.authResponse != nil { + c.authResponseMu.Unlock() return nil, fmt.Errorf("previous authentication is still in progress") } - c.raCtx = &CPContext{ctx, make(chan packets.ControlPacket, 1)} - c.mu.Unlock() + c.authResponse = authResp + c.authResponseMu.Unlock() defer func() { - c.mu.Lock() - c.raCtx = nil - c.mu.Unlock() + c.authResponseMu.Lock() + c.authResponse = nil + c.authResponseMu.Unlock() }() c.debug.Println("sending AUTH") - if _, err := a.Packet().WriteTo(c.Conn); err != nil { + if _, err := a.Packet().WriteTo(c.config.Conn); err != nil { return nil, err } + c.config.PingHandler.PacketSent() var rp packets.ControlPacket select { case <-ctx.Done(): - if ctxErr := ctx.Err(); ctxErr != nil { - c.debug.Println(fmt.Sprintf("terminated due to context: %v", ctxErr)) - return nil, ctxErr - } - case rp = <-c.raCtx.Return: + ctxErr := ctx.Err() + c.debug.Println(fmt.Sprintf("terminated due to context waiting for AUTH: %v", ctxErr)) + return nil, ctxErr + case rp = <-authResp: } switch rp.Type { case packets.AUTH: - //If we've received one here it must be successful, the only way - //to abort a reauth is a server initiated disconnect + // If we've received one here it must be successful, the only way + // to abort a reauth is a server initiated disconnect return AuthResponseFromPacketAuth(rp.Content.(*packets.Auth)), nil case packets.DISCONNECT: return AuthResponseFromPacketDisconnect(rp.Content.(*packets.Disconnect)), nil @@ -626,50 +672,52 @@ func (c *Client) Subscribe(ctx context.Context, s *Subscribe) (*Suback, error) { for _, sub := range s.Subscriptions { if strings.ContainsAny(sub.Topic, "#+") { // Using a wildcard in a subscription when not supported - return nil, fmt.Errorf("cannot subscribe to %s, server does not support wildcards", sub.Topic) + return nil, fmt.Errorf("%w: cannot subscribe to %s, server does not support wildcards", ErrInvalidArguments, sub.Topic) } } } if !c.serverProps.SubIDAvailable && s.Properties != nil && s.Properties.SubscriptionIdentifier != nil { - return nil, fmt.Errorf("cannot send subscribe with subID set, server does not support subID") + return nil, fmt.Errorf("%w: cannot send subscribe with subID set, server does not support subID", ErrInvalidArguments) } if !c.serverProps.SharedSubAvailable { for _, sub := range s.Subscriptions { if strings.HasPrefix(sub.Topic, "$share") { - return nil, fmt.Errorf("cannont subscribe to %s, server does not support shared subscriptions", sub.Topic) + return nil, fmt.Errorf("%w: cannont subscribe to %s, server does not support shared subscriptions", ErrInvalidArguments, sub.Topic) } } } c.debug.Printf("subscribing to %+v", s.Subscriptions) - subCtx, cf := context.WithTimeout(ctx, c.PacketTimeout) - defer cf() - cpCtx := &CPContext{subCtx, make(chan packets.ControlPacket, 1)} - + ret := make(chan packets.ControlPacket, 1) sp := s.Packet() - - mid, err := c.MIDs.Request(cpCtx) - if err != nil { + if err := c.config.Session.AddToSession(ctx, sp, ret); err != nil { return nil, err } - defer c.MIDs.Free(mid) - sp.PacketID = mid - c.debug.Println("sending SUBSCRIBE") - if _, err := sp.WriteTo(c.Conn); err != nil { + // From this point on the message is in store, and ret will receive something regardless of whether we succeed in + // writing the packet to the connection or not. + if _, err := sp.WriteTo(c.config.Conn); err != nil { + // The packet will remain in the session state until `Session` is notified of the disconnection. return nil, err } + c.config.PingHandler.PacketSent() + c.debug.Println("waiting for SUBACK") + subCtx, cf := context.WithTimeout(ctx, c.config.PacketTimeout) + defer cf() var sap packets.ControlPacket select { case <-subCtx.Done(): - if ctxErr := subCtx.Err(); ctxErr != nil { - c.debug.Println(fmt.Sprintf("terminated due to context: %v", ctxErr)) - return nil, ctxErr - } - case sap = <-cpCtx.Return: + ctxErr := subCtx.Err() + c.debug.Println(fmt.Sprintf("terminated due to context waiting for SUBACK: %v", ctxErr)) + return nil, ctxErr + case sap = <-ret: + } + + if sap.Type == 0 { // default ControlPacket indicates we are shutting down + return nil, ErrConnectionLost } if sap.Type != packets.SUBACK { @@ -706,33 +754,35 @@ func (c *Client) Subscribe(ctx context.Context, s *Subscribe) (*Suback, error) { // is returned from the function, along with any errors. func (c *Client) Unsubscribe(ctx context.Context, u *Unsubscribe) (*Unsuback, error) { c.debug.Printf("unsubscribing from %+v", u.Topics) - unsubCtx, cf := context.WithTimeout(ctx, c.PacketTimeout) - defer cf() - cpCtx := &CPContext{unsubCtx, make(chan packets.ControlPacket, 1)} - + ret := make(chan packets.ControlPacket, 1) up := u.Packet() - - mid, err := c.MIDs.Request(cpCtx) - if err != nil { + if err := c.config.Session.AddToSession(ctx, up, ret); err != nil { return nil, err } - defer c.MIDs.Free(mid) - up.PacketID = mid - c.debug.Println("sending UNSUBSCRIBE") - if _, err := up.WriteTo(c.Conn); err != nil { + // From this point on the message is in store, and ret will receive something regardless of whether we succeed in + // writing the packet to the connection or not + if _, err := up.WriteTo(c.config.Conn); err != nil { + // The packet will remain in the session state until `Session` is notified of the disconnection. return nil, err } - c.debug.Println("waiting for UNSUBACK") + c.config.PingHandler.PacketSent() + + unsubCtx, cf := context.WithTimeout(ctx, c.config.PacketTimeout) + defer cf() var uap packets.ControlPacket + c.debug.Println("waiting for UNSUBACK") select { case <-unsubCtx.Done(): - if ctxErr := unsubCtx.Err(); ctxErr != nil { - c.debug.Println(fmt.Sprintf("terminated due to context: %v", ctxErr)) - return nil, ctxErr - } - case uap = <-cpCtx.Return: + ctxErr := unsubCtx.Err() + c.debug.Println(fmt.Sprintf("terminated due to context waiting for UNSUBACK: %v", ctxErr)) + return nil, ctxErr + case uap = <-ret: + } + + if uap.Type == 0 { // default ControlPacket indicates we are shutting down + return nil, ErrConnectionLost } if uap.Type != packets.UNSUBACK { @@ -764,27 +814,52 @@ func (c *Client) Unsubscribe(ctx context.Context, u *Unsubscribe) (*Unsuback, er } // Publish is used to send a publication to the MQTT server. -// It is passed a pre-prepared Publish packet and blocks waiting for -// the appropriate response, or for the timeout to fire. -// Any response message is returned from the function, along with any errors. +// It is passed a pre-prepared Publish packet and blocks waiting for the appropriate response, or for the timeout to fire. +// A PublishResponse is returned, which is relevant for QOS1+. For QOS0, a default success response is returned. +// Note that a message may still be delivered even if Publish times out (once the message is part of the session state, +// it may even be delivered following an application restart). +// Warning: Publish may outlive the connection when QOS1+ (managed in `session_state`) func (c *Client) Publish(ctx context.Context, p *Publish) (*PublishResponse, error) { + return c.PublishWithOptions(ctx, p, PublishOptions{}) +} + +type PublishMethod int + +const ( + PublishMethod_Blocking PublishMethod = iota // by default PublishWithOptions will block until the publish transaction is complete + PublishMethod_AsyncSend // PublishWithOptions will add the message to the session and then return (no method to check status is provided) +) + +// PublishOptions enables the behaviour of Publish to be modified +type PublishOptions struct { + // Method enables a degree of control over how PublishWithOptions operates + Method PublishMethod +} + +// PublishWithOptions is used to send a publication to the MQTT server (with options to customise its behaviour) +// It is passed a pre-prepared Publish packet and, by default, blocks waiting for the appropriate response, or for the +// timeout to fire. A PublishResponse is returned, which is relevant for QOS1+. For QOS0, a default success response is returned. +// Note that a message may still be delivered even if Publish times out (once the message is part of the session state, +// it may even be delivered following an application restart). +// Warning: Publish may outlive the connection when QOS1+ (managed in `session_state`) +func (c *Client) PublishWithOptions(ctx context.Context, p *Publish, o PublishOptions) (*PublishResponse, error) { if p.QoS > c.serverProps.MaximumQoS { - return nil, fmt.Errorf("cannot send Publish with QoS %d, server maximum QoS is %d", p.QoS, c.serverProps.MaximumQoS) + return nil, fmt.Errorf("%w: cannot send Publish with QoS %d, server maximum QoS is %d", ErrInvalidArguments, p.QoS, c.serverProps.MaximumQoS) } if p.Properties != nil && p.Properties.TopicAlias != nil { if c.serverProps.TopicAliasMaximum > 0 && *p.Properties.TopicAlias > c.serverProps.TopicAliasMaximum { - return nil, fmt.Errorf("cannot send publish with TopicAlias %d, server topic alias maximum is %d", *p.Properties.TopicAlias, c.serverProps.TopicAliasMaximum) + return nil, fmt.Errorf("%w: cannot send publish with TopicAlias %d, server topic alias maximum is %d", ErrInvalidArguments, *p.Properties.TopicAlias, c.serverProps.TopicAliasMaximum) } } if !c.serverProps.RetainAvailable && p.Retain { - return nil, fmt.Errorf("cannot send Publish with retain flag set, server does not support retained messages") + return nil, fmt.Errorf("%w: cannot send Publish with retain flag set, server does not support retained messages", ErrInvalidArguments) } if (p.Properties == nil || p.Properties.TopicAlias == nil) && p.Topic == "" { - return nil, fmt.Errorf("cannot send a publish with no TopicAlias and no Topic set") + return nil, fmt.Errorf("%w: cannot send a publish with no TopicAlias and no Topic set", ErrInvalidArguments) } - if c.ClientConfig.PublishHook != nil { - c.ClientConfig.PublishHook(p) + if c.config.PublishHook != nil { + c.config.PublishHook(p) } c.debug.Printf("sending message to %s", p.Topic) @@ -794,46 +869,54 @@ func (c *Client) Publish(ctx context.Context, p *Publish) (*PublishResponse, err switch p.QoS { case 0: c.debug.Println("sending QoS0 message") - if _, err := pb.WriteTo(c.Conn); err != nil { + if _, err := pb.WriteTo(c.config.Conn); err != nil { + go c.error(err) return nil, err } - return nil, nil + c.config.PingHandler.PacketSent() + return &PublishResponse{}, nil case 1, 2: - return c.publishQoS12(ctx, pb) + return c.publishQoS12(ctx, pb, o) } - return nil, fmt.Errorf("QoS isn't 0, 1 or 2") + return nil, fmt.Errorf("%w: QoS isn't 0, 1 or 2", ErrInvalidArguments) } -func (c *Client) publishQoS12(ctx context.Context, pb *packets.Publish) (*PublishResponse, error) { +func (c *Client) publishQoS12(ctx context.Context, pb *packets.Publish, o PublishOptions) (*PublishResponse, error) { c.debug.Println("sending QoS12 message") - pubCtx, cf := context.WithTimeout(ctx, c.PacketTimeout) + pubCtx, cf := context.WithTimeout(ctx, c.config.PacketTimeout) defer cf() - if err := c.serverInflight.Acquire(pubCtx, 1); err != nil { + + ret := make(chan packets.ControlPacket, 1) + if err := c.config.Session.AddToSession(pubCtx, pb, ret); err != nil { return nil, err } - defer c.serverInflight.Release(1) - cpCtx := &CPContext{pubCtx, make(chan packets.ControlPacket, 1)} - mid, err := c.MIDs.Request(cpCtx) - if err != nil { - return nil, err + // From this point on the message is in store, and ret will receive something regardless of whether we succeed in + // writing the packet to the connection + if _, err := pb.WriteTo(c.config.Conn); err != nil { + c.debug.Printf("failed to write packet %d to connection: %s", pb.PacketID, err) + if o.Method == PublishMethod_AsyncSend { + return nil, ErrNetworkErrorAfterStored // Async send, so we don't wait for the response (may add callbacks in the future to enable user to obtain status) + } } - defer c.MIDs.Free(mid) - pb.PacketID = mid + c.config.PingHandler.PacketSent() - if _, err := pb.WriteTo(c.Conn); err != nil { - return nil, err + if o.Method == PublishMethod_AsyncSend { + return nil, nil // Async send, so we don't wait for the response (may add callbacks in the future to enable user to obtain status) } - var resp packets.ControlPacket + var resp packets.ControlPacket select { case <-pubCtx.Done(): - if ctxErr := pubCtx.Err(); ctxErr != nil { - c.debug.Println(fmt.Sprintf("terminated due to context: %v", ctxErr)) - return nil, ctxErr - } - case resp = <-cpCtx.Return: + ctxErr := pubCtx.Err() + c.debug.Println(fmt.Sprintf("terminated due to context waiting for Publish ack: %v", ctxErr)) + return nil, ctxErr + case resp = <-ret: + } + + if resp.Type == 0 { // default ControlPacket indicates we are shutting down + return nil, errors.New("PUBLISH transmitted but not fully acknowledged at time of shutdown") } switch pb.QoS { @@ -867,7 +950,7 @@ func (c *Client) publishQoS12(ctx context.Context, pb *packets.Publish) (*Publis } func (c *Client) expectConnack(packet chan<- *packets.Connack, errs chan<- error) { - recv, err := packets.ReadPacket(c.Conn) + recv, err := packets.ReadPacket(c.config.Conn) if err != nil { errs <- err return @@ -877,17 +960,17 @@ func (c *Client) expectConnack(packet chan<- *packets.Connack, errs chan<- error c.debug.Println("received CONNACK") if r.ReasonCode == packets.ConnackSuccess && r.Properties != nil && r.Properties.AuthMethod != "" { // Successful connack and AuthMethod is defined, must have successfully authed during connect - go c.AuthHandler.Authenticated() + go c.config.AuthHandler.Authenticated() } packet <- r case *packets.Auth: c.debug.Println("received AUTH") - if c.AuthHandler == nil { + if c.config.AuthHandler == nil { errs <- fmt.Errorf("enhanced authentication flow started but no AuthHandler configured") return } c.debug.Println("sending AUTH") - _, err := c.AuthHandler.Authenticate(AuthFromPacketAuth(r)).Packet().WriteTo(c.Conn) + _, err := c.config.AuthHandler.Authenticate(AuthFromPacketAuth(r)).Packet().WriteTo(c.config.Conn) if err != nil { errs <- fmt.Errorf("error sending authentication packet: %w", err) return @@ -905,23 +988,77 @@ func (c *Client) expectConnack(packet chan<- *packets.Connack, errs chan<- error // (and if it does this function returns any error) the network connection // is closed. func (c *Client) Disconnect(d *Disconnect) error { - c.debug.Println("disconnecting") - _, err := d.Packet().WriteTo(c.Conn) + c.debug.Println("disconnecting", d) + _, err := d.Packet().WriteTo(c.config.Conn) c.close() - c.workers.Wait() return err } +// AddOnPublishReceived adds a function that will be called when a PUBLISH is received +// The new function will be called after any functions already in the list +// Returns a function that can be called to remove the callback +func (c *Client) AddOnPublishReceived(f func(PublishReceived) (bool, error)) func() { + c.onPublishReceivedMu.Lock() + defer c.onPublishReceivedMu.Unlock() + + c.onPublishReceived = append(c.onPublishReceived, f) + + // We insert a unique ID into the same position in onPublishReceivedTracker; this enables us to + // remove the handler later (without complicating onPublishReceived which will be called frequently) + var id int +idLoop: + for id = 0; ; id++ { + for _, used := range c.onPublishReceivedTracker { + if used == id { + continue idLoop + } + } + break + } + c.onPublishReceivedTracker = append(c.onPublishReceivedTracker, id) + + return func() { + c.onPublishReceivedMu.Lock() + defer c.onPublishReceivedMu.Unlock() + for pos, storedID := range c.onPublishReceivedTracker { + if id == storedID { + c.onPublishReceivedTracker = append(c.onPublishReceivedTracker[:pos], c.onPublishReceivedTracker[pos+1:]...) + c.onPublishReceived = append(c.onPublishReceived[:pos], c.onPublishReceived[pos+1:]...) + } + } + } +} + +// ClientID retrieves the client ID from the config (sometimes used in handlers that require the ID) +func (c *Client) ClientID() string { + return c.config.ClientID +} + // SetDebugLogger takes an instance of the paho Logger interface // and sets it to be used by the debug log endpoint -func (c *Client) SetDebugLogger(l Logger) { +func (c *Client) SetDebugLogger(l log.Logger) { c.debug = l + if c.config.autoCloseSession { // If we created the session store then it should use the same logger + c.config.Session.SetDebugLogger(l) + } + if c.config.defaultPinger { // Debug logger is set after the client is created so need to copy it to pinger + c.config.PingHandler.SetDebug(c.debug) + } } // SetErrorLogger takes an instance of the paho Logger interface // and sets it to be used by the error log endpoint -func (c *Client) SetErrorLogger(l Logger) { +func (c *Client) SetErrorLogger(l log.Logger) { c.errors = l + if c.config.autoCloseSession { // If we created the session store then it should use the same logger + c.config.Session.SetErrorLogger(l) + } +} + +// TerminateConnectionForTest closes the active connection (if any). This function is intended for testing only, it +// simulates connection loss which supports testing QOS1 and 2 message delivery. +func (c *Client) TerminateConnectionForTest() { + _ = c.config.Conn.Close() } diff --git a/vendor/github.com/eclipse/paho.golang/paho/cp_auth.go b/vendor/github.com/eclipse/paho.golang/paho/cp_auth.go index 6ccef9b47de..46b64f8e2af 100644 --- a/vendor/github.com/eclipse/paho.golang/paho/cp_auth.go +++ b/vendor/github.com/eclipse/paho.golang/paho/cp_auth.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package paho import "github.com/eclipse/paho.golang/packets" diff --git a/vendor/github.com/eclipse/paho.golang/paho/cp_connack.go b/vendor/github.com/eclipse/paho.golang/paho/cp_connack.go index 2a525eb48b0..ef8a58605f6 100644 --- a/vendor/github.com/eclipse/paho.golang/paho/cp_connack.go +++ b/vendor/github.com/eclipse/paho.golang/paho/cp_connack.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package paho import ( diff --git a/vendor/github.com/eclipse/paho.golang/paho/cp_connect.go b/vendor/github.com/eclipse/paho.golang/paho/cp_connect.go index 8d731764d14..76adb183a0d 100644 --- a/vendor/github.com/eclipse/paho.golang/paho/cp_connect.go +++ b/vendor/github.com/eclipse/paho.golang/paho/cp_connect.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package paho import "github.com/eclipse/paho.golang/packets" @@ -26,7 +41,6 @@ type ( WillDelayInterval *uint32 ReceiveMaximum *uint16 TopicAliasMaximum *uint16 - MaximumQOS *byte MaximumPacketSize *uint32 User UserProperties RequestProblemInfo bool @@ -47,7 +61,6 @@ func (c *Connect) InitProperties(p *packets.Properties) { RequestProblemInfo: true, ReceiveMaximum: p.ReceiveMaximum, TopicAliasMaximum: p.TopicAliasMaximum, - MaximumQOS: p.MaximumQOS, MaximumPacketSize: p.MaximumPacketSize, User: UserPropertiesFromPacketUser(p.User), } @@ -122,7 +135,6 @@ func (c *Connect) Packet() *packets.Connect { WillDelayInterval: c.Properties.WillDelayInterval, ReceiveMaximum: c.Properties.ReceiveMaximum, TopicAliasMaximum: c.Properties.TopicAliasMaximum, - MaximumQOS: c.Properties.MaximumQOS, MaximumPacketSize: c.Properties.MaximumPacketSize, User: c.Properties.User.ToPacketProperties(), } diff --git a/vendor/github.com/eclipse/paho.golang/paho/cp_disconnect.go b/vendor/github.com/eclipse/paho.golang/paho/cp_disconnect.go index 5caa85b147c..ac5931c40a1 100644 --- a/vendor/github.com/eclipse/paho.golang/paho/cp_disconnect.go +++ b/vendor/github.com/eclipse/paho.golang/paho/cp_disconnect.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package paho import "github.com/eclipse/paho.golang/packets" diff --git a/vendor/github.com/eclipse/paho.golang/paho/cp_publish.go b/vendor/github.com/eclipse/paho.golang/paho/cp_publish.go index 1bb9654b341..7f845e3d844 100644 --- a/vendor/github.com/eclipse/paho.golang/paho/cp_publish.go +++ b/vendor/github.com/eclipse/paho.golang/paho/cp_publish.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package paho import ( @@ -12,6 +27,7 @@ type ( Publish struct { PacketID uint16 QoS byte + duplicate bool // private because this should only ever be set in paho/session Retain bool Topic string Properties *PublishProperties @@ -52,26 +68,34 @@ func (p *Publish) InitProperties(prop *packets.Properties) { // returns a paho library Publish func PublishFromPacketPublish(p *packets.Publish) *Publish { v := &Publish{ - PacketID: p.PacketID, - QoS: p.QoS, - Retain: p.Retain, - Topic: p.Topic, - Payload: p.Payload, + PacketID: p.PacketID, + QoS: p.QoS, + duplicate: p.Duplicate, + Retain: p.Retain, + Topic: p.Topic, + Payload: p.Payload, } v.InitProperties(p.Properties) return v } +// Duplicate returns true if the duplicate flag is set (the server sets this if the message has +// been sent previously; this does not necessarily mean the client has previously processed the message). +func (p *Publish) Duplicate() bool { + return p.duplicate +} + // Packet returns a packets library Publish from the paho Publish // on which it is called func (p *Publish) Packet() *packets.Publish { v := &packets.Publish{ - PacketID: p.PacketID, - QoS: p.QoS, - Retain: p.Retain, - Topic: p.Topic, - Payload: p.Payload, + PacketID: p.PacketID, + QoS: p.QoS, + Duplicate: p.duplicate, + Retain: p.Retain, + Topic: p.Topic, + Payload: p.Payload, } if p.Properties != nil { v.Properties = &packets.Properties{ @@ -90,6 +114,9 @@ func (p *Publish) Packet() *packets.Publish { } func (p *Publish) String() string { + if p == nil { + return "Publish==nil" + } var b bytes.Buffer fmt.Fprintf(&b, "topic: %s qos: %d retain: %t\n", p.Topic, p.QoS, p.Retain) diff --git a/vendor/github.com/eclipse/paho.golang/paho/cp_pubresp.go b/vendor/github.com/eclipse/paho.golang/paho/cp_pubresp.go index 0c4e174aa00..bf47fca569e 100644 --- a/vendor/github.com/eclipse/paho.golang/paho/cp_pubresp.go +++ b/vendor/github.com/eclipse/paho.golang/paho/cp_pubresp.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package paho import "github.com/eclipse/paho.golang/packets" diff --git a/vendor/github.com/eclipse/paho.golang/paho/cp_suback.go b/vendor/github.com/eclipse/paho.golang/paho/cp_suback.go index c1034c26c30..f9bce038933 100644 --- a/vendor/github.com/eclipse/paho.golang/paho/cp_suback.go +++ b/vendor/github.com/eclipse/paho.golang/paho/cp_suback.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package paho import "github.com/eclipse/paho.golang/packets" diff --git a/vendor/github.com/eclipse/paho.golang/paho/cp_subscribe.go b/vendor/github.com/eclipse/paho.golang/paho/cp_subscribe.go index 52dc54017f2..04298accf0e 100644 --- a/vendor/github.com/eclipse/paho.golang/paho/cp_subscribe.go +++ b/vendor/github.com/eclipse/paho.golang/paho/cp_subscribe.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package paho import "github.com/eclipse/paho.golang/packets" diff --git a/vendor/github.com/eclipse/paho.golang/paho/cp_unsuback.go b/vendor/github.com/eclipse/paho.golang/paho/cp_unsuback.go index 15ca83885a0..d9f1ad2c127 100644 --- a/vendor/github.com/eclipse/paho.golang/paho/cp_unsuback.go +++ b/vendor/github.com/eclipse/paho.golang/paho/cp_unsuback.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package paho import "github.com/eclipse/paho.golang/packets" diff --git a/vendor/github.com/eclipse/paho.golang/paho/cp_unsubscribe.go b/vendor/github.com/eclipse/paho.golang/paho/cp_unsubscribe.go index 375b917c8f6..ff20acf9978 100644 --- a/vendor/github.com/eclipse/paho.golang/paho/cp_unsubscribe.go +++ b/vendor/github.com/eclipse/paho.golang/paho/cp_unsubscribe.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package paho import "github.com/eclipse/paho.golang/packets" diff --git a/vendor/github.com/eclipse/paho.golang/paho/cp_utils.go b/vendor/github.com/eclipse/paho.golang/paho/cp_utils.go index 2d7995f5ca7..a1ca35ebef0 100644 --- a/vendor/github.com/eclipse/paho.golang/paho/cp_utils.go +++ b/vendor/github.com/eclipse/paho.golang/paho/cp_utils.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package paho import ( diff --git a/vendor/github.com/eclipse/paho.golang/paho/log/test.go b/vendor/github.com/eclipse/paho.golang/paho/log/test.go new file mode 100644 index 00000000000..4e8ff4d7e3b --- /dev/null +++ b/vendor/github.com/eclipse/paho.golang/paho/log/test.go @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +package log + +import ( + "sync" + "time" +) + +// test implements a logger than can be passed a testing.T (which will only output logs for failed tests) + +// testLogger contains the logging functions provided by testing.T +type testLogger interface { + Log(args ...interface{}) + Logf(format string, args ...interface{}) +} + +// The TestLog type is an adapter to allow the use of testing.T as a paho.Logger. +// With this implementation, log messages will only be output when a test fails (and will be associated with the test). +type TestLog struct { + sync.Mutex + l testLogger + prefix string +} + +// NewTestLogger accepts a testLogger (e.g. Testing.T) and a prefix (added to messages logged) and returns a Logger +func NewTestLogger(l testLogger, prefix string) *TestLog { + return &TestLog{ + l: l, + prefix: prefix, + } +} + +// Println prints a line to the log +// Println its arguments in the test log (only printed if the test files or appropriate arguments passed to go test). +func (t *TestLog) Println(v ...interface{}) { + t.Lock() + defer t.Unlock() + if t.l != nil { + t.l.Log(append([]interface{}{time.Now().Format(time.RFC3339Nano), t.prefix}, v...)...) + } +} + +// Printf formats its arguments according to the format, analogous to fmt.Printf, and +// records the text in the test log (only printed if the test files or appropriate arguments passed to go test). +func (t *TestLog) Printf(format string, v ...interface{}) { + t.Lock() + defer t.Unlock() + if t.l != nil { + t.l.Logf(time.Now().Format(time.RFC3339Nano)+" "+t.prefix+format, v...) + } +} + +// Stop prevents future logging +// func (t *TestLog) Stop() { +// t.Lock() +// defer t.Unlock() +// t.l = nil +// } diff --git a/vendor/github.com/eclipse/paho.golang/paho/trace.go b/vendor/github.com/eclipse/paho.golang/paho/log/trace.go similarity index 55% rename from vendor/github.com/eclipse/paho.golang/paho/trace.go rename to vendor/github.com/eclipse/paho.golang/paho/log/trace.go index 586c9239891..8363f7254e4 100644 --- a/vendor/github.com/eclipse/paho.golang/paho/trace.go +++ b/vendor/github.com/eclipse/paho.golang/paho/log/trace.go @@ -1,4 +1,19 @@ -package paho +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +package log type ( // Logger interface allows implementations to provide to this package any diff --git a/vendor/github.com/eclipse/paho.golang/paho/message_ids.go b/vendor/github.com/eclipse/paho.golang/paho/message_ids.go deleted file mode 100644 index ad287b5c755..00000000000 --- a/vendor/github.com/eclipse/paho.golang/paho/message_ids.go +++ /dev/null @@ -1,110 +0,0 @@ -package paho - -import ( - "context" - "errors" - "sync" - - "github.com/eclipse/paho.golang/packets" -) - -const ( - midMin uint16 = 1 - midMax uint16 = 65535 -) - -// ErrorMidsExhausted is returned from Request() when there are no -// free message ids to be used. -var ErrorMidsExhausted = errors.New("all message ids in use") - -// MIDService defines the interface for a struct that handles the -// relationship between message ids and CPContexts -// Request() takes a *CPContext and returns a uint16 that is the -// messageid that should be used by the code that called Request() -// Get() takes a uint16 that is a messageid and returns the matching -// *CPContext that the MIDService has associated with that messageid -// Free() takes a uint16 that is a messageid and instructs the MIDService -// to mark that messageid as available for reuse -// Clear() resets the internal state of the MIDService -type MIDService interface { - Request(*CPContext) (uint16, error) - Get(uint16) *CPContext - Free(uint16) - Clear() -} - -// CPContext is the struct that is used to return responses to -// ControlPackets that have them, eg: the suback to a subscribe. -// The response packet is send down the Return channel and the -// Context is used to track timeouts. -type CPContext struct { - Context context.Context - Return chan packets.ControlPacket -} - -// MIDs is the default MIDService provided by this library. -// It uses a slice of *CPContext to track responses -// to messages with a messageid tracking the last used message id -type MIDs struct { - sync.Mutex - lastMid uint16 - index []*CPContext // index of slice is (messageid - 1) -} - -// Request is the library provided MIDService's implementation of -// the required interface function() -func (m *MIDs) Request(c *CPContext) (uint16, error) { - m.Lock() - defer m.Unlock() - - // Scan from lastMid to end of range. - for i := m.lastMid; i < midMax; i++ { - if m.index[i] != nil { - continue - } - m.index[i] = c - m.lastMid = i + 1 - return i + 1, nil - } - // Scan from start of range to lastMid - for i := uint16(0); i < m.lastMid; i++ { - if m.index[i] != nil { - continue - } - m.index[i] = c - m.lastMid = i + 1 - return i + 1, nil - } - - return 0, ErrorMidsExhausted -} - -// Get is the library provided MIDService's implementation of -// the required interface function() -func (m *MIDs) Get(i uint16) *CPContext { - // 0 Packet Identifier is invalid but just in case handled with returning nil to avoid panic. - if i == 0 { - return nil - } - m.Lock() - defer m.Unlock() - return m.index[i-1] -} - -// Free is the library provided MIDService's implementation of -// the required interface function() -func (m *MIDs) Free(i uint16) { - // 0 Packet Identifier is invalid but just in case handled to avoid panic. - if i == 0 { - return - } - m.Lock() - m.index[i-1] = nil - m.Unlock() -} - -// Clear is the library provided MIDService's implementation of -// the required interface function() -func (m *MIDs) Clear() { - m.index = make([]*CPContext, int(midMax)) -} diff --git a/vendor/github.com/eclipse/paho.golang/paho/noop_persistence.go b/vendor/github.com/eclipse/paho.golang/paho/noop_persistence.go deleted file mode 100644 index d2d15704f1e..00000000000 --- a/vendor/github.com/eclipse/paho.golang/paho/noop_persistence.go +++ /dev/null @@ -1,23 +0,0 @@ -package paho - -import "github.com/eclipse/paho.golang/packets" - -type noopPersistence struct{} - -func (n *noopPersistence) Open() {} - -func (n *noopPersistence) Put(id uint16, cp packets.ControlPacket) {} - -func (n *noopPersistence) Get(id uint16) packets.ControlPacket { - return packets.ControlPacket{} -} - -func (n *noopPersistence) All() []packets.ControlPacket { - return nil -} - -func (n *noopPersistence) Delete(id uint16) {} - -func (n *noopPersistence) Close() {} - -func (n *noopPersistence) Reset() {} diff --git a/vendor/github.com/eclipse/paho.golang/paho/persistence.go b/vendor/github.com/eclipse/paho.golang/paho/persistence.go deleted file mode 100644 index f02b846cc2d..00000000000 --- a/vendor/github.com/eclipse/paho.golang/paho/persistence.go +++ /dev/null @@ -1,98 +0,0 @@ -package paho - -import ( - "sync" - - "github.com/eclipse/paho.golang/packets" -) - -// Persistence is an interface of the functions for a struct -// that is used to persist ControlPackets. -// Open() is an initialiser to prepare the Persistence for use -// Put() takes a uint16 which is a messageid and a ControlPacket -// to persist against that messageid -// Get() takes a uint16 which is a messageid and returns the -// persisted ControlPacket from the Persistence for that messageid -// All() returns a slice of all ControlPackets persisted -// Delete() takes a uint16 which is a messageid and deletes the -// associated stored ControlPacket from the Persistence -// Close() closes the Persistence -// Reset() clears the Persistence and prepares it to be reused -type Persistence interface { - Open() - Put(uint16, packets.ControlPacket) - Get(uint16) packets.ControlPacket - All() []packets.ControlPacket - Delete(uint16) - Close() - Reset() -} - -// MemoryPersistence is an implementation of a Persistence -// that stores the ControlPackets in memory using a map -type MemoryPersistence struct { - sync.RWMutex - packets map[uint16]packets.ControlPacket -} - -// Open is the library provided MemoryPersistence's implementation of -// the required interface function() -func (m *MemoryPersistence) Open() { - m.Lock() - m.packets = make(map[uint16]packets.ControlPacket) - m.Unlock() -} - -// Put is the library provided MemoryPersistence's implementation of -// the required interface function() -func (m *MemoryPersistence) Put(id uint16, cp packets.ControlPacket) { - m.Lock() - m.packets[id] = cp - m.Unlock() -} - -// Get is the library provided MemoryPersistence's implementation of -// the required interface function() -func (m *MemoryPersistence) Get(id uint16) packets.ControlPacket { - m.RLock() - defer m.RUnlock() - return m.packets[id] -} - -// All is the library provided MemoryPersistence's implementation of -// the required interface function() -func (m *MemoryPersistence) All() []packets.ControlPacket { - m.Lock() - defer m.RUnlock() - ret := make([]packets.ControlPacket, len(m.packets)) - - for _, cp := range m.packets { - ret = append(ret, cp) - } - - return ret -} - -// Delete is the library provided MemoryPersistence's implementation of -// the required interface function() -func (m *MemoryPersistence) Delete(id uint16) { - m.Lock() - delete(m.packets, id) - m.Unlock() -} - -// Close is the library provided MemoryPersistence's implementation of -// the required interface function() -func (m *MemoryPersistence) Close() { - m.Lock() - m.packets = nil - m.Unlock() -} - -// Reset is the library provided MemoryPersistence's implementation of -// the required interface function() -func (m *MemoryPersistence) Reset() { - m.Lock() - m.packets = make(map[uint16]packets.ControlPacket) - m.Unlock() -} diff --git a/vendor/github.com/eclipse/paho.golang/paho/pinger.go b/vendor/github.com/eclipse/paho.golang/paho/pinger.go index e135d25acfe..0eb28ccb22c 100644 --- a/vendor/github.com/eclipse/paho.golang/paho/pinger.go +++ b/vendor/github.com/eclipse/paho.golang/paho/pinger.go @@ -1,122 +1,149 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package paho import ( + "context" "fmt" "net" "sync" - "sync/atomic" "time" "github.com/eclipse/paho.golang/packets" + "github.com/eclipse/paho.golang/paho/log" ) -// PingFailHandler is a type for the function that is invoked -// when we have sent a Pingreq to the server and not received -// a Pingresp within 1.5x our pingtimeout -type PingFailHandler func(error) - -// Pinger is an interface of the functions for a struct that is -// used to manage sending PingRequests and responding to -// PingResponses -// Start() takes a net.Conn which is a connection over which an -// MQTT session has already been established, and a time.Duration -// of the keepalive setting passed to the server when the MQTT -// session was established. -// Stop() is used to stop the Pinger -// PingResp() is the function that is called by the Client when -// a PingResponse is received -// SetDebug() is used to pass in a Logger to be used to log debug -// information, for example sharing a logger with the main client type Pinger interface { - Start(net.Conn, time.Duration) - Stop() + // Run starts the pinger. It blocks until the pinger is stopped. + // If the pinger stops due to an error, it returns the error. + // If the keepAlive is 0, it returns nil immediately. + // Run() may be called multiple times, but only after prior instances have terminated. + Run(ctx context.Context, conn net.Conn, keepAlive uint16) error + + // PacketSent is called when a packet is sent to the server. + PacketSent() + + // PingResp is called when a PINGRESP is received from the server. PingResp() - SetDebug(Logger) + + // SetDebug sets the logger for debugging. + // It is not thread-safe and must be called before Run() to avoid race conditions. + SetDebug(log.Logger) } -// PingHandler is the library provided default Pinger -type PingHandler struct { - mu sync.Mutex - lastPing time.Time - conn net.Conn - stop chan struct{} - pingFailHandler PingFailHandler - pingOutstanding int32 - debug Logger +// DefaultPinger is the default implementation of Pinger. +type DefaultPinger struct { + lastPacketSent time.Time + lastPingResponse time.Time + + debug log.Logger + + running bool // Used to prevent concurrent calls to Run + + mu sync.Mutex // Protects all of the above } -// DefaultPingerWithCustomFailHandler returns an instance of the -// default Pinger but with a custom PingFailHandler that is called -// when the client has not received a response to a PingRequest -// within the appropriate amount of time -func DefaultPingerWithCustomFailHandler(pfh PingFailHandler) *PingHandler { - return &PingHandler{ - pingFailHandler: pfh, - debug: NOOPLogger{}, +// NewDefaultPinger creates a DefaultPinger +func NewDefaultPinger() *DefaultPinger { + return &DefaultPinger{ + debug: log.NOOPLogger{}, } } -// Start is the library provided Pinger's implementation of -// the required interface function() -func (p *PingHandler) Start(c net.Conn, pt time.Duration) { +// Run starts the pinger; blocks until done (either context cancelled or error encountered) +func (p *DefaultPinger) Run(ctx context.Context, conn net.Conn, keepAlive uint16) error { + if keepAlive == 0 { + p.debug.Println("Run() returning immediately due to keepAlive == 0") + return nil + } + if conn == nil { + return fmt.Errorf("conn is nil") + } p.mu.Lock() - p.conn = c - p.stop = make(chan struct{}) + if p.running { + p.mu.Unlock() + return fmt.Errorf("Run() already in progress") + } + p.running = true p.mu.Unlock() - checkTicker := time.NewTicker(pt / 4) - defer checkTicker.Stop() + defer func() { + p.mu.Lock() + p.running = false + p.mu.Unlock() + }() + + interval := time.Duration(keepAlive) * time.Second + timer := time.NewTimer(0) // Immediately send first pingreq + // If timer is not stopped, it cannot be garbage collected until it fires. + defer timer.Stop() + var lastPingSent time.Time + // errCh should be buffered, so that the goroutine sending the error does not block if the context is cancelled + errCh := make(chan error, 1) for { select { - case <-p.stop: - return - case <-checkTicker.C: - if atomic.LoadInt32(&p.pingOutstanding) > 0 && time.Since(p.lastPing) > (pt+pt>>1) { - p.pingFailHandler(fmt.Errorf("ping resp timed out")) - //ping outstanding and not reset in 1.5 times ping timer - return + case <-ctx.Done(): + return nil + case t := <-timer.C: + p.mu.Lock() + lastPingResponse := p.lastPingResponse + pingDue := p.lastPacketSent.Add(interval) + p.mu.Unlock() + + if !lastPingSent.IsZero() && lastPingSent.After(lastPingResponse) { + p.debug.Printf("DefaultPinger PINGRESP timeout") + return fmt.Errorf("PINGRESP timed out") } - if time.Since(p.lastPing) >= pt { - //time to send a ping - if _, err := packets.NewControlPacket(packets.PINGREQ).WriteTo(p.conn); err != nil { - if p.pingFailHandler != nil { - p.pingFailHandler(err) - } - return - } - atomic.AddInt32(&p.pingOutstanding, 1) - p.lastPing = time.Now() - p.debug.Println("pingHandler sending ping request") + + if t.Before(pingDue) { + // A Control Packet has been sent since we last checked, meaning the ping can be delayed + timer.Reset(pingDue.Sub(t)) + continue } + lastPingSent = time.Now() + go func() { + // WriteTo may not complete within KeepAlive period due to slow/unstable network. + // For instance, if a huge message is sent over a very slow link at the same time as PINGREQ packet, + // the Write operation may block for longer than KeepAlive interval. + // Note: connection closure unblocks the Write operation. So, the goroutine is not leaked. + if _, err := packets.NewControlPacket(packets.PINGREQ).WriteTo(conn); err != nil { + p.debug.Printf("DefaultPinger packet write error: %v", err) + errCh <- fmt.Errorf("failed to send PINGREQ: %w", err) + } + }() + timer.Reset(interval) + case err := <-errCh: + return err } } } -// Stop is the library provided Pinger's implementation of -// the required interface function() -func (p *PingHandler) Stop() { +func (p *DefaultPinger) PacketSent() { p.mu.Lock() defer p.mu.Unlock() - if p.stop == nil { - return - } - p.debug.Println("pingHandler stopping") - select { - case <-p.stop: - //Already stopped, do nothing - default: - close(p.stop) - } + p.lastPacketSent = time.Now() } -// PingResp is the library provided Pinger's implementation of -// the required interface function() -func (p *PingHandler) PingResp() { - p.debug.Println("pingHandler resetting pingOutstanding") - atomic.StoreInt32(&p.pingOutstanding, 0) +func (p *DefaultPinger) PingResp() { + p.mu.Lock() + defer p.mu.Unlock() + p.lastPingResponse = time.Now() } -// SetDebug sets the logger l to be used for printing debug -// information for the pinger -func (p *PingHandler) SetDebug(l Logger) { - p.debug = l +func (p *DefaultPinger) SetDebug(debug log.Logger) { + p.mu.Lock() + defer p.mu.Unlock() + p.debug = debug } diff --git a/vendor/github.com/eclipse/paho.golang/paho/router.go b/vendor/github.com/eclipse/paho.golang/paho/router.go index 05031596f29..dc6fa7062f5 100644 --- a/vendor/github.com/eclipse/paho.golang/paho/router.go +++ b/vendor/github.com/eclipse/paho.golang/paho/router.go @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + package paho import ( @@ -5,10 +20,14 @@ import ( "sync" "github.com/eclipse/paho.golang/packets" + "github.com/eclipse/paho.golang/paho/log" ) // MessageHandler is a type for a function that is invoked // by a Router when it has received a Publish. +// MessageHandlers should complete quickly (start a go routine for +// long-running processes) and should not call functions within the +// paho instance that triggered them (due to potential deadlocks). type MessageHandler func(*Publish) // Router is an interface of the functions for a struct that is @@ -24,16 +43,17 @@ type Router interface { RegisterHandler(string, MessageHandler) UnregisterHandler(string) Route(*packets.Publish) - SetDebugLogger(Logger) + SetDebugLogger(log.Logger) } // StandardRouter is a library provided implementation of a Router that // allows for unique and multiple MessageHandlers per topic type StandardRouter struct { sync.RWMutex - subscriptions map[string][]MessageHandler - aliases map[uint16]string - debug Logger + defaultHandler MessageHandler + subscriptions map[string][]MessageHandler + aliases map[uint16]string + debug log.Logger } // NewStandardRouter instantiates and returns an instance of a StandardRouter @@ -41,10 +61,19 @@ func NewStandardRouter() *StandardRouter { return &StandardRouter{ subscriptions: make(map[string][]MessageHandler), aliases: make(map[uint16]string), - debug: NOOPLogger{}, + debug: log.NOOPLogger{}, } } +// NewStandardRouterWithDefault instantiates and returns an instance of a StandardRouter +// with the default handler set to the value passed in (for convenience when creating +// handler inline). +func NewStandardRouterWithDefault(h MessageHandler) *StandardRouter { + r := NewStandardRouter() + r.DefaultHandler(h) + return r +} + // RegisterHandler is the library provided StandardRouter's // implementation of the required interface function() func (r *StandardRouter) RegisterHandler(topic string, h MessageHandler) { @@ -78,7 +107,7 @@ func (r *StandardRouter) Route(pb *packets.Publish) { if pb.Properties.TopicAlias != nil { r.debug.Println("message is using topic aliasing") if pb.Topic != "" { - //Register new alias + // Register new alias r.debug.Printf("registering new topic alias '%d' for topic '%s'", *pb.Properties.TopicAlias, m.Topic) r.aliases[*pb.Properties.TopicAlias] = pb.Topic } @@ -90,22 +119,37 @@ func (r *StandardRouter) Route(pb *packets.Publish) { topic = m.Topic } + handlerCalled := false for route, handlers := range r.subscriptions { if match(route, topic) { r.debug.Println("found handler for:", route) for _, handler := range handlers { handler(m) + handlerCalled = true } } } + + if !handlerCalled && r.defaultHandler != nil { + r.defaultHandler(m) + } } // SetDebugLogger sets the logger l to be used for printing debug // information for the router -func (r *StandardRouter) SetDebugLogger(l Logger) { +func (r *StandardRouter) SetDebugLogger(l log.Logger) { r.debug = l } +// DefaultHandler sets handler to be called for messages that don't trigger another handler +// Pass nil to unset. +func (r *StandardRouter) DefaultHandler(h MessageHandler) { + r.debug.Println("registering default handler") + r.Lock() + defer r.Unlock() + r.defaultHandler = h +} + func match(route, topic string) bool { return route == topic || routeIncludesTopic(route, topic) } @@ -153,60 +197,12 @@ func topicSplit(topic string) []string { return strings.Split(topic, "/") } -// SingleHandlerRouter is a library provided implementation of a Router -// that stores only a single MessageHandler and invokes this MessageHandler -// for all received Publishes -type SingleHandlerRouter struct { - sync.Mutex - aliases map[uint16]string - handler MessageHandler - debug Logger -} - -// NewSingleHandlerRouter instantiates and returns an instance of a SingleHandlerRouter -func NewSingleHandlerRouter(h MessageHandler) *SingleHandlerRouter { - return &SingleHandlerRouter{ - aliases: make(map[uint16]string), - handler: h, - debug: NOOPLogger{}, - } -} - -// RegisterHandler is the library provided SingleHandlerRouter's -// implementation of the required interface function() -func (s *SingleHandlerRouter) RegisterHandler(topic string, h MessageHandler) { - s.debug.Println("registering handler for:", topic) - s.handler = h -} - -// UnregisterHandler is the library provided SingleHandlerRouter's -// implementation of the required interface function() -func (s *SingleHandlerRouter) UnregisterHandler(topic string) {} - -// Route is the library provided SingleHandlerRouter's -// implementation of the required interface function() -func (s *SingleHandlerRouter) Route(pb *packets.Publish) { - m := PublishFromPacketPublish(pb) - - s.debug.Println("routing message for:", m.Topic) - - if pb.Properties.TopicAlias != nil { - s.debug.Println("message is using topic aliasing") - if pb.Topic != "" { - //Register new alias - s.debug.Printf("registering new topic alias '%d' for topic '%s'", *pb.Properties.TopicAlias, m.Topic) - s.aliases[*pb.Properties.TopicAlias] = pb.Topic - } - if t, ok := s.aliases[*pb.Properties.TopicAlias]; ok { - s.debug.Printf("aliased topic '%d' translates to '%s'", *pb.Properties.TopicAlias, m.Topic) - m.Topic = t - } - } - s.handler(m) -} - -// SetDebugLogger sets the logger l to be used for printing debug -// information for the router -func (s *SingleHandlerRouter) SetDebugLogger(l Logger) { - s.debug = l +// NewSingleHandlerRouter instantiates a router that will call the passed in message handler for all +// inbound messages (assuming `RegisterHandler` is never called). +// +// Deprecated: SingleHandlerRouter has been removed because it did not meet the requirements set out +// in the `Router` interface documentation. This function is only included to maintain compatibility, +// but there are limits (this version does not ignore calls to `RegisterHandler`). +func NewSingleHandlerRouter(h MessageHandler) *StandardRouter { + return NewStandardRouterWithDefault(h) } diff --git a/vendor/github.com/eclipse/paho.golang/paho/session/session.go b/vendor/github.com/eclipse/paho.golang/paho/session/session.go new file mode 100644 index 00000000000..a8d4a534945 --- /dev/null +++ b/vendor/github.com/eclipse/paho.golang/paho/session/session.go @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +package session + +import ( + "context" + "errors" + "io" + + "github.com/eclipse/paho.golang/packets" + paholog "github.com/eclipse/paho.golang/paho/log" +) + +// The session state includes: +// * Inflight QOS1/2 Publish transactions (both sent and received) +// * All requests + +var ( + ErrNoConnection = errors.New("no connection available") // We are not in-between a call to ConAckReceived and ConnectionLost + ErrPacketIdentifiersExhausted = errors.New("all packet identifiers in use") // There are no available Packet IDs +) + +// Packet provides sufficient functionality to enable a packet to be transmitted with a packet identifier +type Packet interface { + SetIdentifier(uint16) // Sets the packet identifier + Type() byte // Gets the packet type + WriteTo(io.Writer) (int64, error) +} + +// SessionManager will manage the mqtt session state; note that the state may outlast a single `Client` instance +type SessionManager interface { + // ConAckReceived must be called when a CONNACK has been received (with no error). If an error is returned + // then the connection will be dropped. + ConAckReceived(io.Writer, *packets.Connect, *packets.Connack) error + + // ConnectionLost must be called whenever the connection is lost or a DISCONNECT packet is received. It can be + // called multiple times for the same event as long as ConAckReceived is not called in the interim. + ConnectionLost(dp *packets.Disconnect) error + + // AddToSession adds a packet to the session state (including allocation of a message identifier). + // This should only be used for packets that impact the session state (which does not include QOS0 publish). + // If this function returns a nil then: + // - A message Identifier has been added to the passed in packet + // - If a `PUBLISH` then a slot has been allocated (function will block if RECEIVE MAXIMUM messages are inflight) + // - Publish messages will have been written to the store (and will be automatically transmitted if a new connection + // is established before the message is fully acknowledged - subject to state rules in the MQTTv5 spec) + // - Something will be sent to `resp` when either the message is fully acknowledged or the packet is removed from + // the session (in which case nil will be sent). + // + // If the function returns an error, then any actions taken will be rewound prior to return. + AddToSession(ctx context.Context, packet Packet, resp chan<- packets.ControlPacket) error + + // PacketReceived must be called when any packet with a packet identifier is received. It will make any required + // response and pass any `PUBLISH` messages that need to be passed to the user via the channel. + PacketReceived(*packets.ControlPacket, chan<- *packets.Publish) error + + // Ack must be called when the client message handlers have completed (or, if manual acknowledgements are enabled, + // when`client.ACK()` has been called - note the potential issues discussed in issue #160. + Ack(pb *packets.Publish) error + + // Close shuts down the session store, this will release any blocked calls + // Note: `paho` will only call this if it created the session (i.e. it was not passed in the config) + Close() error + + // SetErrorLogger enables error logging via the passed logger (not thread safe) + SetErrorLogger(l paholog.Logger) + + // SetDebugLogger enables debug logging via the passed logger (not thread safe) + SetDebugLogger(l paholog.Logger) +} diff --git a/vendor/github.com/eclipse/paho.golang/paho/session/state/readme.md b/vendor/github.com/eclipse/paho.golang/paho/session/state/readme.md new file mode 100644 index 00000000000..cbeec0f88ea --- /dev/null +++ b/vendor/github.com/eclipse/paho.golang/paho/session/state/readme.md @@ -0,0 +1,5 @@ +paho.golang/paho/session/state +============================== + +This is an implementation of the `paho.golang/paho/session.SessionManager` interface and is the implementation used +by default (should be suitable for mose use cases but can be replaced if it does not meet your needs). \ No newline at end of file diff --git a/vendor/github.com/eclipse/paho.golang/paho/session/state/sendquota.go b/vendor/github.com/eclipse/paho.golang/paho/session/state/sendquota.go new file mode 100644 index 00000000000..d48f053037d --- /dev/null +++ b/vendor/github.com/eclipse/paho.golang/paho/session/state/sendquota.go @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +package state + +import ( + "context" + "errors" + "fmt" + "sync" +) + +// Implements send quota as described in section 4.9 of the spec. This is used to honour the receive-maximum +// received from the broker; each time a qos1/2 PUBLISH is to be sent `Acquire` must be called, and this will +// block until a slot is available (`Release` is called when the message is fully acknowledged). + +// This function was previously performed by `golang.org/x/sync/semaphore` but, as per the MQTT spec: +// +// > The send quota is not incremented if it is already equal to the initial send quota. The attempt to increment above +// > the initial send quota might be caused by the re-transmission of a PUBREL packet after a new Network Connection is +// > established. +// +// The result of this happening with `semaphore` is a `panic` which is not ideal. +// It is also possible (as per issue #179) that bugs, or unexpected circumstances, may result in the same situation. For +// example: if the local session state is lost but there is a session state on the server (meaning it sends an unexpected +// PUBACK). +// +// Note: If the broker does not correctly acknowledge messages, then the quota will be consumed over time. There +// should probably be a process to drop the connection if there are no slots available and no acknowledgements have been +// received recently. + +// ErrUnexpectedRelease is for logging only (to help identify if there are issues with state management) +var ErrUnexpectedRelease = errors.New("release called when quota at initial value") + +// newSendQuota creates a new tracker limited to quota concurrent messages +func newSendQuota(quota uint16) *sendQuota { + w := &sendQuota{initialQuota: quota, quota: quota} + return w +} + +// sendQuota provides a way to bound concurrent access to a resource. +// The callers can request access with a given weight. +type sendQuota struct { + mu sync.Mutex + initialQuota uint16 + quota uint16 + waiters []chan<- struct{} // using a slice because would generally expect this to be small +} + +// Retransmit takes a slot for a message that is being redelivered and will never block. +// This is not in compliance with the MQTT v5 spec and should be removed in the future. +func (s *sendQuota) Retransmit() error { + return s.acquire(context.Background(), true) +} + +// Acquire waits for a slot to become available so a message can be published +// If ctx is already done, Acquire may still succeed without blocking. +func (s *sendQuota) Acquire(ctx context.Context) error { + return s.acquire(ctx, false) +} + +// acquire attempts to allocate a slot for a message to be published +// If noWait is true quota will be ignored and the call will return immediately, otherwise acquire will block +// until a slot is available. +func (s *sendQuota) acquire(ctx context.Context, noWait bool) error { + s.mu.Lock() + if noWait || (s.quota > 0 && len(s.waiters) == 0) { + s.quota-- // Note: can go < 0 if noWait used + s.mu.Unlock() + return nil + } + + // We need to join the queue + ready := make(chan struct{}) + s.waiters = append(s.waiters, ready) + s.mu.Unlock() + + var err error + select { + case <-ctx.Done(): + err = ctx.Err() + s.mu.Lock() + select { + case <-ready: // If ready then already removed from s.waiters + // Acquired the semaphore after we were cancelled. Rather than trying to + // fix up the queue, just pretend we didn't notice the cancellation. + err = nil + fmt.Println("quota released entry but ready so nil error ", s.quota) + default: + // Remove ourselves from the list of waiters + for i, r := range s.waiters { + if ready == r { + s.waiters = append(s.waiters[:i], s.waiters[i+1:]...) + } + } + } + s.mu.Unlock() + case <-ready: // Note that quota already accounts for this item + } + return err +} + +// Release releases slot +func (s *sendQuota) Release() error { + s.mu.Lock() + defer s.mu.Unlock() + + if s.quota >= 0 && len(s.waiters) > 0 { // Possible quota could go negative when using noWait + close(s.waiters[0]) + s.waiters = append(s.waiters[:0], s.waiters[1:]...) + return nil + } + if s.quota < s.initialQuota { + s.quota++ + return nil + } + return ErrUnexpectedRelease +} diff --git a/vendor/github.com/eclipse/paho.golang/paho/session/state/state.go b/vendor/github.com/eclipse/paho.golang/paho/session/state/state.go new file mode 100644 index 00000000000..bd197046e99 --- /dev/null +++ b/vendor/github.com/eclipse/paho.golang/paho/session/state/state.go @@ -0,0 +1,739 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +package state + +import ( + "context" + "errors" + "fmt" + "io" + "sync" + "time" + + "github.com/eclipse/paho.golang/packets" + paholog "github.com/eclipse/paho.golang/paho/log" + "github.com/eclipse/paho.golang/paho/session" + "github.com/eclipse/paho.golang/paho/store/memory" +) + +// The Session State, as per the MQTT spec, contains: +// +// > QoS 1 and QoS 2 messages which have been sent to the Server, but have not been completely acknowledged. +// > QoS 2 messages which have been received from the Server, but have not been completely acknowledged. +// +// and, importantly, is used when resending as follows: +// +// > When a Client reconnects with Clean Start set to 0 and a session is present, both the Client and Server MUST resend +// > any unacknowledged PUBLISH packets (where QoS > 0) and PUBREL packets using their original Packet Identifiers. This +// > is the only circumstance where a Client or Server is REQUIRED to resend messages. Clients and Servers MUST NOT +// > resend messages at any other time +// +// There are a few other areas where the State is important: +// * When allocating a new packet identifier we need to know what Id's are already in the session state. +// * If a QOS2 Publish with `DUP=TRUE` is received then we should not pass it to the client if we have previously +// sent a `PUBREC` (indicating that the message has already been processed). +// * Some subscribers may need a transaction (i.e. commit transaction when `PUBREL` received), this is not implemented +// here, but the option is left open. +// +// This means that the following information may need to be retained after the connection is lost: +// * The IDs of any transactions initiated by the client (so that we don't reuse IDs and can notify the requester (if +// known) when a response is received or the request is removed from the state). +// * For client initiated publish: +// * Outgoing `PUBLISH` packets to allow resend. +// * Outgoing `PUBREL` packets to allow resend. +// * For server initiated publish: +// * Outgoing `PUBREL` packets. The fact that this has been sent indicates that the user app has acknowledged the +// message, and it should not be re-presented (doing so would breach the "exactly once" requirement). +// * In memory only - the fact that a QOS2 PUBLISH has been received and sent to the handler, but not acknowledged. +// This allows us to avoid presenting the message a second time (if the application is restarted, we have no option +// but to re-present it because we have no way of knowing if the application completed handling it). +// +// It is important to note that there are packets with identifiers that do not form part of the session state +// (SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK). Whilst these will never be stored to disk, it is important to track +// the packet IDs to ensure we don't reuse them. +// For packets relating to client-initiated transactions sent during a `session.State` lifetime we also want to link +// a channel to the message ID so that we can notify our user when the transaction is complete (allowing a call to, for +// instance `Publish()` to block until the message is fully acknowledged even if we disconnect/reconnect in the interim. + +const ( + midMin uint16 = 1 + midMax uint16 = 65535 +) + +type ( + // clientGenerated holds information on client-generated packets (e.g. an outgoing SUBSCRIBE request) + clientGenerated struct { + packetType byte // The type of the last packet sent (i.e. PUBLISH, SUBSCRIBE or UNSUBSCRIBE) - 0 means unknown until loaded from the store + + // When a message is fully acknowledged, we need to let the requester know by sending the final response to this + // channel. One and only one message will be sent (the channel will then be closed to ensure this!). + // We also guarantee to always send to the channel (assuming there is a clean shutdown) so that the end user knows + // the status of the request. + responseChan chan<- packets.ControlPacket + } +) + +// State manages the session state. The client will send messages that may impact the state via +// us, and we will maintain the session state +type State struct { + mu sync.Mutex // protects whole struct (operations should be quick, so the impact of multiple mutexes is likely to be low) + connectionLostAt time.Time // Time that the connection was lost + sessionExpiryInterval uint32 // The session expiry interval sent with the most recent CONNECT packet + + conn io.Writer // current connection or nil if we are not connected + connCtx context.Context // Context will be closed if the connection is lost (only valid when conn != nil) + connCtxCancel func() // Cancels the above context + + // client store - holds packets where the message ID was generated on the client (i.e. by paho.golang) + clientPackets map[uint16]clientGenerated // Store relating to messages sent TO the server + clientStore storer // Used to store session state that survives connection loss + lastMid uint16 // The message ID most recently issued + + // server store - holds packets where the message ID was generated on the server + serverPackets map[uint16]byte // The last packet received from the server with this ID (cleared when the transaction is complete) + serverStore storer // Used to store session state that survives connection loss + + // The number of messages in flight needs to be limited, as per receive maximum received from the server. + inflight *sendQuota + + debug paholog.Logger + errors paholog.Logger +} + +// New creates a new state which will persist information using the passed in storer's. +func New(client storer, server storer) *State { + return &State{ + clientStore: client, + serverStore: server, + debug: paholog.NOOPLogger{}, + errors: paholog.NOOPLogger{}, + } +} + +// NewInMemory returns a default State that stores all information in memory +func NewInMemory() *State { + return &State{ + clientStore: memory.New(), + serverStore: memory.New(), + debug: paholog.NOOPLogger{}, + errors: paholog.NOOPLogger{}, + } +} + +// Close closes the session state +func (s *State) Close() error { + s.mu.Lock() + defer s.mu.Unlock() + s.connectionLost(nil) // Connection may be up in which case we need to cleanup. + for packetID, cg := range s.clientPackets { + cg.responseChan <- packets.ControlPacket{} // Default control packet indicates that we are shutting down (TODO: better solution?) + delete(s.clientPackets, packetID) + } + return nil +} + +// ConAckReceived will be called when the client receives a CONACK that indicates the connection has been successfully +// established. This indicates that a new connection is live and the passed in connection should be used going forward. +// It is also the trigger to resend any queued messages. Note that this function should not be called concurrently with +// others (we should not begin sending/receiving packets until after the CONACK has been processed). +// TODO: Add errors() function so we can notify the client of errors whilst transmitting the session stuff? +func (s *State) ConAckReceived(conn io.Writer, cp *packets.Connect, ca *packets.Connack) error { + // We could use cp.Properties.SessionExpiryInterval / ca.Properties.SessionExpiryInterval to clear the session + // after the specified time period (if the Session Expiry Interval is absent the value in the CONNECT Packet used) + // however, this is not something the generic client can really accomplish (forks may wish to do this!). + s.mu.Lock() + defer s.mu.Unlock() + if s.conn != nil { + s.errors.Println("ConAckReceived called whilst connection active (you MUST call ConnectionLost before starting a new connection") + _ = s.connectionLost(nil) // assume the connection dropped + } + s.conn = conn + s.connCtx, s.connCtxCancel = context.WithCancel(context.Background()) + + // If the Server accepts a connection with Clean Start set to 1, the Server MUST set Session Present to 0 in the + // CONNACK packet in addition to setting a 0x00 (Success) Reason Code in the CONNACK packet [MQTT-3.2.2-2]. + // If the Server accepts a connection with Clean Start set to 0 and the Server has Session State for the ClientID, + // it MUST set Session Present to 1 in the CONNACK packet, otherwise it MUST set Session Present to 0 in the CONNACK + // packet. In both cases, it MUST set a 0x00 (Success) Reason Code in the CONNACK packet [MQTT-3.2.2-3]. + if !ca.SessionPresent { + s.debug.Println("no session present - cleaning session state") + s.clean() + } + inFlight := uint16(len(s.clientPackets)) + s.debug.Printf("%d inflight transactions upon connection", inFlight) + + // "If the Session Expiry Interval is absent, the Session Expiry Interval in the CONNECT packet is used." + // If the Session Expiry Interval is absent the value 0 is used. If it is set to 0, or is absent, the Session ends + // when the Network Connection is closed (3.1.2.11.2). + if ca.Properties != nil && ca.Properties.SessionExpiryInterval != nil { + s.sessionExpiryInterval = *ca.Properties.SessionExpiryInterval + } else if cp.Properties != nil && cp.Properties.SessionExpiryInterval != nil { + s.sessionExpiryInterval = *cp.Properties.SessionExpiryInterval + } else { + s.sessionExpiryInterval = 0 + } + + // If clientPackets already exists, we re-use it so that the responseChan survives the reconnection + // the map will be populated/repopulated when we retransmit the messages. + if s.clientPackets == nil { + s.clientPackets = make(map[uint16]clientGenerated) // This will be populated whilst packets are resent + } + + if s.serverPackets == nil { + if err := s.loadServerSession(ca); err != nil { + return fmt.Errorf("failed to server session: %w", err) + } + } + + // As per section 4.9 "The send quota and Receive Maximum value are not preserved across Network Connections" + recvMax := uint16(65535) // Default as per MQTT spec + if ca.Properties != nil && ca.Properties.ReceiveMaximum != nil { + recvMax = *ca.Properties.ReceiveMaximum + } + s.inflight = newSendQuota(recvMax) + + // Now we need to resend any packets in the store; this must happen in order, the simplest approach is to complete + // the sending them before returning. + toResend, err := s.clientStore.List() + if err != nil { + return fmt.Errorf("failed to load stored message ids: %w", err) + } + s.debug.Printf("retransmitting %d messages", len(toResend)) + for _, id := range toResend { + s.debug.Printf("resending message ID %d", id) + r, err := s.clientStore.Get(id) + if err != nil { + s.errors.Printf("failed to load packet %d from client store: %s", id, err) + continue + } + + // DUP needs to be set when resending PUBLISH + // Read/parse the full packet, so we can detect corruption (e.g. 0 byte file) + p, err := packets.ReadPacket(r) + if cErr := r.Close(); cErr != nil { + s.errors.Printf("failed to close stored client packet %d: %s", id, cErr) + } + if err != nil { // If the packet cannot be read, we quarantine it; otherwise we may retry infinitely. + if err := s.clientStore.Quarantine(id); err != nil { + s.errors.Printf("failed to quarantine packet %d from client store: %s", id, err) + } + s.errors.Printf("failed to retrieve/parse packet %d from client store: %s", id, err) + continue + } + + switch p.Type { + case packets.PUBLISH: + pub := p.Content.(*packets.Publish) + pub.Duplicate = true + case packets.PUBREL: + default: + if err := s.clientStore.Quarantine(id); err != nil { + s.errors.Printf("failed to quarantine packet %d from client store: %s", id, err) + } + s.errors.Printf("unexpected packet type %d (for packet identifier %d) in client store", p.Type, id) + continue + } + + // The messages being retransmitted form part of the "send quota"; however, as per the V5 spec, + // the limit does not apply to messages being resent (the quota can go under 0) + s.inflight.Retransmit() // This will never block (but is needed to block new messages) + + // Any failure from this point should result in loss of connection (so fatal) + if _, err := p.WriteTo(conn); err != nil { + s.debug.Printf("retransmitting of identifier %d failed: %s", id, err) + return fmt.Errorf("failed to retransmit message (%d): %w", id, err) + } + s.debug.Printf("retransmitted message with identifier %d", id) + // On initial connection, the packet needs to be added to our record of client-generated packets. + if _, ok := s.clientPackets[id]; !ok { + s.clientPackets[id] = clientGenerated{ + packetType: p.Type, + responseChan: make(chan packets.ControlPacket, 1), // Nothing will wait on this + } + } + } + return nil +} + +// loadServerSession should be called once, when the first connection is established. +// It loads the server session state from the store. +// The caller must hold a lock on s.mu +func (s *State) loadServerSession(ca *packets.Connack) error { + s.serverPackets = make(map[uint16]byte) + ids, err := s.serverStore.List() + if err != nil { + return fmt.Errorf("failed to load stored server message ids: %w", err) + } + for _, id := range ids { + r, err := s.serverStore.Get(id) + if err != nil { + s.errors.Printf("failed to load packet %d from server store: %s", id, err) + continue + } + // We only need to know the packet type so there is no need to process the entire packet + byte1 := make([]byte, 1) + _, err = r.Read(byte1) + _ = r.Close() + if err != nil { + if err := s.serverStore.Quarantine(id); err != nil { + s.errors.Printf("failed to quarantine packet %d from server store (failed to read): %s", id, err) + } + s.errors.Printf("packet %d from server store could not be read: %s", id, err) + continue // don't want to fail so quarantine and continue is the best we can do + } + packetType := byte1[0] >> 4 + switch packetType { + case packets.PUBLISH: + s.serverPackets[id] = packets.PUBLISH + case packets.PUBREC: + s.serverPackets[id] = packets.PUBREC + default: + if err := s.serverStore.Quarantine(id); err != nil { + s.errors.Printf("failed to quarantine packet %d from server store: %s", id, err) + } + s.errors.Printf("packet %d from server store had unexpected type %d", id, packetType) + continue // don't want to fail so quarantine and continue is the best we can do + } + } + return nil +} + +// ConnectionLost will be called when the connection is lost; either because we received a DISCONNECT packet or due +// to a network error (`nil` will be passed in) +func (s *State) ConnectionLost(dp *packets.Disconnect) error { + s.mu.Lock() + defer s.mu.Unlock() + return s.connectionLost(dp) +} + +// connectionLost process loss of connection +// Caller MUST have locked c.Mu +func (s *State) connectionLost(dp *packets.Disconnect) error { + if s.conn == nil { + return nil // ConnectionLost may be called multiple times (but call ref Disconnect packet should be first) + } + s.connCtxCancel() + s.conn, s.connCtx, s.connCtxCancel = nil, nil, nil + s.connectionLostAt = time.Now() + + if dp != nil && dp.Properties != nil && dp.Properties.SessionExpiryInterval != nil { + s.sessionExpiryInterval = *dp.Properties.SessionExpiryInterval + } + // The Client and Server MUST store the Session State after the Network Connection is closed if the Session Expiry + // Interval is greater than 0 [MQTT-3.1.2-23] + if s.sessionExpiryInterval == 0 { + s.debug.Println("sessionExpiryInterval is 0 and connection lost - cleaning session state") + s.clean() + } + return nil +} + +// AddToSession adds a packet to the session state (including allocation of a Message Identifier). +// If this function returns a nil then: +// - A slot has been allocated if the packet is a PUBLISH (function will block if RECEIVE MAXIMUM messages are inflight) +// - A message Identifier has been added to the passed in packet +// - Publish messages will have been written to the store (and will be automatically transmitted if a new connection +// is established before the message is fully acknowledged - subject to state rules in the MQTTv5 spec) +// - Something will be sent to `resp` when either the message is fully acknowledged or the packet is removed from +// the session (in which case nil will be sent). +// +// If the function returns an error, then any actions taken will be rewound prior to return. +func (s *State) AddToSession(ctx context.Context, packet session.Packet, resp chan<- packets.ControlPacket) error { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + s.mu.Lock() // There may be a delay waiting for semaphore so check for connection before and after + if s.conn == nil { + s.mu.Unlock() + return session.ErrNoConnection + } + // If the connection is lost whilst we are waiting, then in Acquire should terminate. + connCtx := s.connCtx + s.mu.Unlock() + + // If the connection drops while waiting we should abort + go func() { + select { + case <-connCtx.Done(): + cancel() + case <-ctx.Done(): + } + }() + + pt := packet.Type() + + // Ensure only "RECEIVE MAXIMUM" PUBLISH transactions are in flight at any time + if pt == packets.PUBLISH { + if err := s.inflight.Acquire(ctx); err != nil { + if connCtx.Err() != nil { + return session.ErrNoConnection + } + return err // Allow user to confirm if it was their context that led to termination + } + } + + // We have a slot, so acquire a Message ID + // Need to look at what to do if this fails. Should be infrequent as: + // its a lot of messages + // receive max often defaults to a fairly low value + // Maximum recieve max is 65535 which matches the number of slots (so would also need a SUB/UNSUB in flight). + packetID, err := s.allocateNextPacketId(pt, resp) + if err != nil { + if pt == packets.PUBLISH { + if qErr := s.inflight.Release(); qErr != nil { + s.errors.Printf("quota release due to packet id issue: %s", qErr) + } + } + return err + } + packet.SetIdentifier(packetID) + if pt == packets.PUBLISH { + if err = s.clientStore.Put(packetID, pt, packet); err != nil { + s.mu.Lock() + delete(s.clientPackets, packetID) + s.mu.Unlock() + if qErr := s.inflight.Release(); qErr != nil { + s.errors.Printf("quota release due to store issue: %s", qErr) + } + packet.SetIdentifier(0) // ensure the Message identifier is not used + return err + } + } + return nil +} + +// endClientGenerated should be called when a client-generated transaction has been fully acknowledged +// (or if, due to connection loss, it will never be acknowledged). +func (s *State) endClientGenerated(packetID uint16, recv *packets.ControlPacket) error { + s.mu.Lock() + defer s.mu.Unlock() + if cg, ok := s.clientPackets[packetID]; ok { + cg.responseChan <- *recv + delete(s.clientPackets, packetID) + // Outgoing publish messages will be in the store (replaced with PUBREL that is sent) + if cg.packetType == packets.PUBLISH || cg.packetType == packets.PUBREL { + if qErr := s.inflight.Release(); qErr != nil { + s.errors.Printf("quota release due to %s: %s", recv.PacketType(), qErr) + } + if err := s.clientStore.Delete(packetID); err != nil { + s.errors.Printf("failed to remove message %d from store: %s", packetID, err) + } + } + } else { + s.debug.Println("received a response for a message ID we don't know:", recv.PacketID()) + } + return nil // TODO: Should we return errors here (not much that could be done with them) +} + +// Ack is called when the client message handlers have completed (or, if manual acknowledgements are enabled, when +// `client.ACK()` has been called - this may happen some time after the message was received and it is conceivable that +// the connection may have been dropped and reestablished in the interim). +// See issue 160 re issues when the State is called after the connection is dropped. We assume that the +// user will ensure that all ACK's are completed before the State is applied to a new connection (not doing +// this may have unpredictable results). +func (s *State) Ack(pb *packets.Publish) error { + return s.ack(pb) +} + +// ack sends an acknowledgment of the `PUBLISH` (which will have been received from the server) +// `s.mu` must NOT be locked when this is called. +// Note: Adding properties to the response is not currently supported. If this functionality is added, then it is +// important to note that QOS2 PUBREC's may be resent if a duplicate `PUBLISH` is received. +// This function will only return comms related errors (so caller can assume connection has been lost). +func (s *State) ack(pb *packets.Publish) error { + s.mu.Lock() + defer s.mu.Unlock() + var err error + switch pb.QoS { + case 1: + pa := packets.Puback{ + Properties: &packets.Properties{}, + PacketID: pb.PacketID, + } + if s.conn != nil { + s.debug.Println("sending PUBACK") + _, err = pa.WriteTo(s.conn) + if err != nil { + s.errors.Printf("failed to send PUBACK for %d: %s", pb.PacketID, err) + } + } else { + s.debug.Println("PUBACK not send because connection down") + } + // We don't store outbound PUBACK. The server will retransmit the PUBLISH if the connection is reestablished + // before it receives the ACK. Unfortunately, there is no definitive way to determine if + // such messages are duplicates or not (so we are forced to treat them all as if they are new). + case 2: + pr := packets.Pubrec{ + Properties: &packets.Properties{}, + PacketID: pb.PacketID, + } + if s.conn != nil { + s.debug.Printf("sending PUBREC") + _, err = pr.WriteTo(s.conn) + if err != nil { + s.errors.Printf("failed to send PUBREC for %d: %s", pb.PacketID, err) + } + } else { + s.debug.Println("PUBREC not send because connection down") + } + + // We need to record the fact that a PUBREC has been sent so we can detect receipt of a duplicate `PUBLISH` + // (which should not be passed to the client app) + cp := pr.ToControlPacket() + s.serverStore.Put(pb.PacketID, packets.PUBREC, cp) + s.serverPackets[pb.PacketID] = cp.Type + default: + err = errors.New("ack called but publish not QOS 1 or 2") + } + return err +} + +// PacketReceived should be called whenever one of the following is received: +// `PUBLISH` (QOS1+ only), `PUBACK`, `PUBREC`, `PUBREL`, `PUBCOMP`, `SUBACK`, `UNSUBACK` +// It will handle sending any neccessary response or passing the message to the client. +// pubChan will be sent a `PUBLISH` if applicable (and a receiver must be active whilst this function runs) +func (s *State) PacketReceived(recv *packets.ControlPacket, pubChan chan<- *packets.Publish) error { + // Note: we do a type switch rather than using the packet type because it's safer and easier to understand + switch rp := recv.Content.(type) { + // + // Packets in response to client-generated transactions + // + case *packets.Suback: // Not in store, just need to advise client and free Message Identifier + s.debug.Println("received SUBACK packet with id ", rp.PacketID) + s.endClientGenerated(rp.PacketID, recv) + return nil + case *packets.Unsuback: // Not in store, just need to advise client and free Message Identifier + s.debug.Println("received UNSUBACK packet with id ", rp.PacketID) + s.endClientGenerated(rp.PacketID, recv) + return nil + case *packets.Puback: // QOS 1 initial (and final) response + s.debug.Println("received PUBACK packet with id ", rp.PacketID) + s.endClientGenerated(rp.PacketID, recv) + return nil + case *packets.Pubrec: // Initial response to a QOS2 Publish + s.debug.Println("received PUBREC packet with id ", rp.PacketID) + s.mu.Lock() + _, ok := s.clientPackets[rp.PacketID] + s.mu.Unlock() + if !ok { + pl := packets.Pubrel{ // Respond with "Packet Identifier not found" + PacketID: recv.Content.(*packets.Pubrec).PacketID, + ReasonCode: 0x92, + } + s.debug.Println("sending PUBREL (unknown ID) for ", pl.PacketID) + _, err := pl.WriteTo(s.conn) + if err != nil { + s.errors.Printf("failed to send PUBREL for %d: %s", pl.PacketID, err) + } + } else { + if rp.ReasonCode >= 0x80 { + s.endClientGenerated(rp.PacketID, recv) + } else { + pl := packets.Pubrel{ + PacketID: rp.PacketID, + } + s.debug.Println("sending PUBREL for", rp.PacketID) + // Update the store (we should never resend the PUBLISH after receiving a PUBREL) + if err := s.clientStore.Put(rp.PacketID, packets.PUBREL, &pl); err != nil { + s.errors.Printf("failed to write PUBREL to store for %d: %s", rp.PacketID, err) + } + if _, err := pl.WriteTo(s.conn); err != nil { + s.errors.Printf("failed to send PUBREL for %d: %s", rp.PacketID, err) + } + } + } + return nil + case *packets.Pubcomp: // QOS 2 final response + s.debug.Printf("received PUBCOMP packet with id %d", rp.PacketID) + s.endClientGenerated(rp.PacketID, recv) + return nil + // + // Packets relating to server generated PUBLISH + // + case *packets.Publish: + s.debug.Printf("received QoS%d PUBLISH", rp.QoS) + // There is no need to store the packet because it will be resent if not acknowledged before the connection is + // reestablished. + if rp.QoS > 0 { + if rp.PacketID == 0 { // Invalid + return fmt.Errorf("received QOS %d PUBLISH with 0 PacketID", rp.QoS) + } + if rp.QoS == 2 { + s.mu.Lock() + if lastSent, ok := s.serverPackets[rp.PacketID]; ok { + // If we have sent a PUBREC, that means that the client has already seen this message, so we can + // simply resend the acknowledgment. + if lastSent == packets.PUBREC { + // If the message is not flagged as a duplicate, then something is wrong; to avoid message loss, + // we will treat this as a new message (because it appears there is a session mismatch, and we + // have not actually seen this message). + if rp.Duplicate { + // The client has already seen this message meaning we do not want to resend it and, instead + // immediately acknowledge it. + s.mu.Unlock() // mu must be unlocked to call ack + return s.ack(rp) + } + s.errors.Printf("received duplicate PUBLISH (%d) but dup flag not set (will assume this overwrites old publish)", rp.PacketID) + } else { + s.errors.Printf("received PUBLISH (%d) but lastSent type is %d (unexpected!)", lastSent) + } + } + s.mu.Unlock() + } + } + pubChan <- rp // the message will be passed to router (and thus the end user app) + return nil + case *packets.Pubrel: + s.debug.Println("received PUBREL for", recv.PacketID()) + // Auto respond to pubrels unless failure code + pr := recv.Content.(*packets.Pubrel) + if pr.ReasonCode >= 0x80 { + // Received a failure code meaning the server does not know about the message (so all we can do is to remove + // it from our store). + s.errors.Printf("received PUBREL with reason code %d ", pr.ReasonCode) + return nil + } else { + pc := packets.Pubcomp{ + PacketID: pr.PacketID, + } + s.mu.Lock() + defer s.mu.Unlock() + s.debug.Println("sending PUBCOMP for", pr.PacketID) + var err error + if s.conn != nil { + _, err = pc.WriteTo(s.conn) + if err != nil { + s.errors.Printf("failed to send PUBCOMP for %d: %s", pc.PacketID, err) + } + // Note: If connection is down we do not clear store (because the server will resend PUBREL upon reconnect) + delete(s.serverPackets, pr.PacketID) + if sErr := s.serverStore.Delete(pr.PacketID); sErr != nil { + s.errors.Printf("failed to remove message %d from server store: %s", pr.PacketID, sErr) + } + } + return err + } + default: + s.errors.Printf("State.PacketReceived received unexpected packet: %#v ", rp) + return nil + } +} + +// allocateNextPacketId assigns the next available packet ID +// Callers must NOT hold lock on s.mu +func (s *State) allocateNextPacketId(forPacketType byte, resp chan<- packets.ControlPacket) (uint16, error) { + s.mu.Lock() // There may be a delay waiting for semaphore so check for connection before and after + defer s.mu.Unlock() + + cg := clientGenerated{ + packetType: forPacketType, + responseChan: resp, + } + + // Scan from lastMid to end of range. + for i := s.lastMid + 1; i != 0; i++ { + if _, ok := s.clientPackets[i]; ok { + continue + } + s.clientPackets[i] = cg + s.lastMid = i + return i, nil + } + + // Default struct will set s.lastMid=0 meaning we have already scanned all mids + if s.lastMid == 0 { + s.lastMid = 1 + return 0, session.ErrPacketIdentifiersExhausted + } + + // Scan from start of range to lastMid (use +1 to avoid rolling over when s.lastMid = 65535) + for i := uint16(0); i < s.lastMid; i++ { + if _, ok := s.clientPackets[i+1]; ok { + continue + } + s.clientPackets[i+1] = cg + s.lastMid = i + 1 + return i + 1, nil + } + return 0, session.ErrPacketIdentifiersExhausted +} + +// clean deletes any existing stored session information +// does not touch inflight because this is not part of the session state (so is reset separately) +// caller is responsible for locking s.mu +func (s *State) clean() { + s.debug.Println("State.clean() called") + s.serverPackets = make(map[uint16]byte) + s.clientPackets = make(map[uint16]clientGenerated) + + s.serverStore.Reset() + s.clientStore.Reset() +} + +// clean deletes any existing stored session information +// as per section 4.1 in the spec; The Session State in the Client consists of: +// > · QoS 1 and QoS 2 messages which have been sent to the Server, but have not been completely acknowledged. +// > · QoS 2 messages which have been received from the Server, but have not been completely acknowledged. +// This means that we keep PUBLISH, PUBREC and PUBREL packets. PUBACK and PUBCOMP will not be stored (the MID +// will be free once they have been sent). PUBREC is retained so we can check newly received PUBLISH messages (and +// confirm if they have already been processed). +// We only resend PUBLISH (where QoS > 0) and PUBREL packets (as per spec section 4.4) +// caller is responsible for locking s.mu +func (s *State) tidy(trigger *packets.ControlPacket) { + s.debug.Println("State.tidy() called") + for id, p := range s.serverPackets { + switch p { + case packets.PUBREC: + // For inbound messages, we only retain `PUBREC` messages so that we can determine if a PUBLISH received has + // already been processed (the `PUBREL` will be sent when the message has been processed by our user). + // The broker will resend any `PUBLISH` and `PUBREL` messages, so there is no need to retain those. + default: + delete(s.serverPackets, id) + s.serverStore.Delete(id) + } + } + + for id, p := range s.clientPackets { + // We only need to remember `PUBLISH` and `PUBREL` messages (both originating from a PUBLISH) + if p.packetType != packets.PUBLISH { + delete(s.clientPackets, id) + s.clientStore.Delete(id) + p.responseChan <- packets.ControlPacket{} + } + } +} + +// SetDebugLogger takes an instance of the paho Logger interface +// and sets it to be used by the debug log endpoint +func (s *State) SetDebugLogger(l paholog.Logger) { + s.debug = l +} + +// SetErrorLogger takes an instance of the paho Logger interface +// and sets it to be used by the error log endpoint +func (s *State) SetErrorLogger(l paholog.Logger) { + s.errors = l +} + +// AllocateClientPacketIDForTest is intended for use in tests only. It allocates a packet ID in the client session state +// This feels like a hack but makes it easier to test packet identifier exhaustion +func (s *State) AllocateClientPacketIDForTest(packetID uint16, forPacketType byte, resp chan<- packets.ControlPacket) { + s.mu.Lock() + defer s.mu.Unlock() + s.clientPackets[packetID] = clientGenerated{ + packetType: forPacketType, + responseChan: resp, + } +} diff --git a/vendor/github.com/eclipse/paho.golang/paho/session/state/store.go b/vendor/github.com/eclipse/paho.golang/paho/session/state/store.go new file mode 100644 index 00000000000..b31a8e50ed3 --- /dev/null +++ b/vendor/github.com/eclipse/paho.golang/paho/session/state/store.go @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +package state + +import ( + "io" +) + +// storer must be implemented by session state stores +type storer interface { + Put(packetID uint16, packetType byte, w io.WriterTo) error // Store the packet + Get(packetID uint16) (io.ReadCloser, error) // Retrieve the packet with the specified in ID + Delete(id uint16) error // Removes the message with the specified store ID + + // Quarantine sets the message with the specified store ID into an error state; this may mean deleting it or storing + // it somewhere separate. This is intended for use when a corrupt packet is detected (as this may result in data + // loss, it's beneficial to have access to corrupt packets for analysis). + Quarantine(id uint16) error + + List() ([]uint16, error) // Returns packet IDs in the order they were Put + Reset() error // Clears the store (deleting all messages) +} diff --git a/vendor/github.com/eclipse/paho.golang/paho/store/memory/store.go b/vendor/github.com/eclipse/paho.golang/paho/store/memory/store.go new file mode 100644 index 00000000000..03c52febb46 --- /dev/null +++ b/vendor/github.com/eclipse/paho.golang/paho/store/memory/store.go @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * https://www.eclipse.org/legal/epl-2.0/ + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +package memory + +import ( + "bytes" + "errors" + "fmt" + "io" + "sync" + + "github.com/eclipse/paho.golang/packets" +) + +var ( + ErrNotInStore = errors.New("the requested ID was not found in the store") // Returned when requested ID not found +) + +// memoryPacket is an element in the memory store +type memoryPacket struct { + c int // message count (used for ordering; as this is 32 bit min chance of rolling over seems remote) + p []byte // the packet we are storing +} + +// New creates a Store +func New() *Store { + return &Store{ + data: make(map[uint16]memoryPacket), + } + +} + +// Store is an implementation of a Store that stores the data in memory +type Store struct { + // server store - holds packets where the message ID was generated on the server + sync.Mutex + data map[uint16]memoryPacket // Holds messages initiated by the server (i.e. we will receive the PUBLISH) + c int // sequence counter used to maintain message order +} + +// Put stores the packet +func (m *Store) Put(packetID uint16, packetType byte, w io.WriterTo) error { + m.Lock() + defer m.Unlock() + var buff bytes.Buffer + + _, err := w.WriteTo(&buff) + if err != nil { + panic(err) + } + + m.data[packetID] = memoryPacket{ + c: m.c, + p: buff.Bytes(), + } + m.c++ + return nil +} + +func (m *Store) Get(packetID uint16) (io.ReadCloser, error) { + m.Lock() + defer m.Unlock() + d, ok := m.data[packetID] + if !ok { + return nil, ErrNotInStore + } + return io.NopCloser(bytes.NewReader(d.p)), nil +} + +// Delete removes the message with the specified store ID +func (m *Store) Delete(id uint16) error { + m.Lock() + defer m.Unlock() + if _, ok := m.data[id]; !ok { + // This could be ignored, but reporting it may help reveal other issues + return fmt.Errorf("request to delete packet %d; packet not found", id) + } + delete(m.data, id) + return nil +} + +// Quarantine is called if a corrupt packet is detected. +// There is little we can do other than deleting the packet. +func (m *Store) Quarantine(id uint16) error { + return m.Delete(id) +} + +// List returns packet IDs in the order they were Put +func (m *Store) List() ([]uint16, error) { + m.Lock() + defer m.Unlock() + + ids := make([]uint16, 0, len(m.data)) + seq := make([]int, 0, len(m.data)) + + // Basic insert sort from map ordered by time + // As the map is relatively small, this should be quick enough (data is retrieved infrequently) + itemNo := 0 + var pos int + for i, v := range m.data { + for pos = 0; pos < itemNo; pos++ { + if seq[pos] > v.c { + break + } + } + ids = append(ids[:pos], append([]uint16{i}, ids[pos:]...)...) + seq = append(seq[:pos], append([]int{v.c}, seq[pos:]...)...) + itemNo++ + } + return ids, nil +} + +// Reset clears the store (deleting all messages) +func (m *Store) Reset() error { + m.Lock() + defer m.Unlock() + m.data = make(map[uint16]memoryPacket) + return nil +} + +// String is for debugging purposes; it dumps the content of the store in a readable format +func (m *Store) String() string { + var b bytes.Buffer + for i, c := range m.data { + p, err := packets.ReadPacket(bytes.NewReader(c.p)) + if err != nil { + b.WriteString(fmt.Sprintf("packet %d could not be read: %s\n", i, err)) + continue + } + + b.WriteString(fmt.Sprintf("packet %d is %s\n", i, p)) + } + return b.String() +} diff --git a/vendor/github.com/go-jose/go-jose/v4/.gitignore b/vendor/github.com/go-jose/go-jose/v4/.gitignore new file mode 100644 index 00000000000..eb29ebaefd8 --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/.gitignore @@ -0,0 +1,2 @@ +jose-util/jose-util +jose-util.t.err \ No newline at end of file diff --git a/vendor/github.com/go-jose/go-jose/v4/.golangci.yml b/vendor/github.com/go-jose/go-jose/v4/.golangci.yml new file mode 100644 index 00000000000..2a577a8f95b --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/.golangci.yml @@ -0,0 +1,53 @@ +# https://github.com/golangci/golangci-lint + +run: + skip-files: + - doc_test.go + modules-download-mode: readonly + +linters: + enable-all: true + disable: + - gochecknoglobals + - goconst + - lll + - maligned + - nakedret + - scopelint + - unparam + - funlen # added in 1.18 (requires go-jose changes before it can be enabled) + +linters-settings: + gocyclo: + min-complexity: 35 + +issues: + exclude-rules: + - text: "don't use ALL_CAPS in Go names" + linters: + - golint + - text: "hardcoded credentials" + linters: + - gosec + - text: "weak cryptographic primitive" + linters: + - gosec + - path: json/ + linters: + - dupl + - errcheck + - gocritic + - gocyclo + - golint + - govet + - ineffassign + - staticcheck + - structcheck + - stylecheck + - unused + - path: _test\.go + linters: + - scopelint + - path: jwk.go + linters: + - gocyclo diff --git a/vendor/github.com/go-jose/go-jose/v4/.travis.yml b/vendor/github.com/go-jose/go-jose/v4/.travis.yml new file mode 100644 index 00000000000..48de631b003 --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/.travis.yml @@ -0,0 +1,33 @@ +language: go + +matrix: + fast_finish: true + allow_failures: + - go: tip + +go: + - "1.13.x" + - "1.14.x" + - tip + +before_script: + - export PATH=$HOME/.local/bin:$PATH + +before_install: + - go get -u github.com/mattn/goveralls github.com/wadey/gocovmerge + - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.18.0 + - pip install cram --user + +script: + - go test -v -covermode=count -coverprofile=profile.cov . + - go test -v -covermode=count -coverprofile=cryptosigner/profile.cov ./cryptosigner + - go test -v -covermode=count -coverprofile=cipher/profile.cov ./cipher + - go test -v -covermode=count -coverprofile=jwt/profile.cov ./jwt + - go test -v ./json # no coverage for forked encoding/json package + - golangci-lint run + - cd jose-util && go build && PATH=$PWD:$PATH cram -v jose-util.t # cram tests jose-util + - cd .. + +after_success: + - gocovmerge *.cov */*.cov > merged.coverprofile + - goveralls -coverprofile merged.coverprofile -service=travis-ci diff --git a/vendor/github.com/go-jose/go-jose/v4/CHANGELOG.md b/vendor/github.com/go-jose/go-jose/v4/CHANGELOG.md new file mode 100644 index 00000000000..6f717dbd86e --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/CHANGELOG.md @@ -0,0 +1,96 @@ +# v4.0.4 + +## Fixed + + - Reverted "Allow unmarshalling JSONWebKeySets with unsupported key types" as a + breaking change. See #136 / #137. + +# v4.0.3 + +## Changed + + - Allow unmarshalling JSONWebKeySets with unsupported key types (#130) + - Document that OpaqueKeyEncrypter can't be implemented (for now) (#129) + - Dependency updates + +# v4.0.2 + +## Changed + + - Improved documentation of Verify() to note that JSONWebKeySet is a supported + argument type (#104) + - Defined exported error values for missing x5c header and unsupported elliptic + curves error cases (#117) + +# v4.0.1 + +## Fixed + + - An attacker could send a JWE containing compressed data that used large + amounts of memory and CPU when decompressed by `Decrypt` or `DecryptMulti`. + Those functions now return an error if the decompressed data would exceed + 250kB or 10x the compressed size (whichever is larger). Thanks to + Enze Wang@Alioth and Jianjun Chen@Zhongguancun Lab (@zer0yu and @chenjj) + for reporting. + +# v4.0.0 + +This release makes some breaking changes in order to more thoroughly +address the vulnerabilities discussed in [Three New Attacks Against JSON Web +Tokens][1], "Sign/encrypt confusion", "Billion hash attack", and "Polyglot +token". + +## Changed + + - Limit JWT encryption types (exclude password or public key types) (#78) + - Enforce minimum length for HMAC keys (#85) + - jwt: match any audience in a list, rather than requiring all audiences (#81) + - jwt: accept only Compact Serialization (#75) + - jws: Add expected algorithms for signatures (#74) + - Require specifying expected algorithms for ParseEncrypted, + ParseSigned, ParseDetached, jwt.ParseEncrypted, jwt.ParseSigned, + jwt.ParseSignedAndEncrypted (#69, #74) + - Usually there is a small, known set of appropriate algorithms for a program + to use and it's a mistake to allow unexpected algorithms. For instance the + "billion hash attack" relies in part on programs accepting the PBES2 + encryption algorithm and doing the necessary work even if they weren't + specifically configured to allow PBES2. + - Revert "Strip padding off base64 strings" (#82) + - The specs require base64url encoding without padding. + - Minimum supported Go version is now 1.21 + +## Added + + - ParseSignedCompact, ParseSignedJSON, ParseEncryptedCompact, ParseEncryptedJSON. + - These allow parsing a specific serialization, as opposed to ParseSigned and + ParseEncrypted, which try to automatically detect which serialization was + provided. It's common to require a specific serialization for a specific + protocol - for instance JWT requires Compact serialization. + +[1]: https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf + +# v3.0.2 + +## Fixed + + - DecryptMulti: handle decompression error (#19) + +## Changed + + - jwe/CompactSerialize: improve performance (#67) + - Increase the default number of PBKDF2 iterations to 600k (#48) + - Return the proper algorithm for ECDSA keys (#45) + +## Added + + - Add Thumbprint support for opaque signers (#38) + +# v3.0.1 + +## Fixed + + - Security issue: an attacker specifying a large "p2c" value can cause + JSONWebEncryption.Decrypt and JSONWebEncryption.DecryptMulti to consume large + amounts of CPU, causing a DoS. Thanks to Matt Schwager (@mschwager) for the + disclosure and to Tom Tervoort for originally publishing the category of attack. + https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf diff --git a/vendor/github.com/go-jose/go-jose/v4/CONTRIBUTING.md b/vendor/github.com/go-jose/go-jose/v4/CONTRIBUTING.md new file mode 100644 index 00000000000..4b4805add65 --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/CONTRIBUTING.md @@ -0,0 +1,9 @@ +# Contributing + +If you would like to contribute code to go-jose you can do so through GitHub by +forking the repository and sending a pull request. + +When submitting code, please make every effort to follow existing conventions +and style in order to keep the code as readable as possible. Please also make +sure all tests pass by running `go test`, and format your code with `go fmt`. +We also recommend using `golint` and `errcheck`. diff --git a/vendor/github.com/go-jose/go-jose/v4/LICENSE b/vendor/github.com/go-jose/go-jose/v4/LICENSE new file mode 100644 index 00000000000..d6456956733 --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/github.com/go-jose/go-jose/v4/README.md b/vendor/github.com/go-jose/go-jose/v4/README.md new file mode 100644 index 00000000000..02b5749546b --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/README.md @@ -0,0 +1,106 @@ +# Go JOSE + +[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v4.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v4) +[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v4/jwt.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v4/jwt) +[![license](https://img.shields.io/badge/license-apache_2.0-blue.svg?style=flat)](https://raw.githubusercontent.com/go-jose/go-jose/master/LICENSE) +[![test](https://img.shields.io/github/checks-status/go-jose/go-jose/v4)](https://github.com/go-jose/go-jose/actions) + +Package jose aims to provide an implementation of the Javascript Object Signing +and Encryption set of standards. This includes support for JSON Web Encryption, +JSON Web Signature, and JSON Web Token standards. + +## Overview + +The implementation follows the +[JSON Web Encryption](https://dx.doi.org/10.17487/RFC7516) (RFC 7516), +[JSON Web Signature](https://dx.doi.org/10.17487/RFC7515) (RFC 7515), and +[JSON Web Token](https://dx.doi.org/10.17487/RFC7519) (RFC 7519) specifications. +Tables of supported algorithms are shown below. The library supports both +the compact and JWS/JWE JSON Serialization formats, and has optional support for +multiple recipients. It also comes with a small command-line utility +([`jose-util`](https://pkg.go.dev/github.com/go-jose/go-jose/jose-util)) +for dealing with JOSE messages in a shell. + +**Note**: We use a forked version of the `encoding/json` package from the Go +standard library which uses case-sensitive matching for member names (instead +of [case-insensitive matching](https://www.ietf.org/mail-archive/web/json/current/msg03763.html)). +This is to avoid differences in interpretation of messages between go-jose and +libraries in other languages. + +### Versions + +[Version 4](https://github.com/go-jose/go-jose) +([branch](https://github.com/go-jose/go-jose/tree/main), +[doc](https://pkg.go.dev/github.com/go-jose/go-jose/v4), [releases](https://github.com/go-jose/go-jose/releases)) is the current stable version: + + import "github.com/go-jose/go-jose/v4" + +The old [square/go-jose](https://github.com/square/go-jose) repo contains the prior v1 and v2 versions, which +are still useable but not actively developed anymore. + +Version 3, in this repo, is still receiving security fixes but not functionality +updates. + +### Supported algorithms + +See below for a table of supported algorithms. Algorithm identifiers match +the names in the [JSON Web Algorithms](https://dx.doi.org/10.17487/RFC7518) +standard where possible. The Godoc reference has a list of constants. + + Key encryption | Algorithm identifier(s) + :------------------------- | :------------------------------ + RSA-PKCS#1v1.5 | RSA1_5 + RSA-OAEP | RSA-OAEP, RSA-OAEP-256 + AES key wrap | A128KW, A192KW, A256KW + AES-GCM key wrap | A128GCMKW, A192GCMKW, A256GCMKW + ECDH-ES + AES key wrap | ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW + ECDH-ES (direct) | ECDH-ES1 + Direct encryption | dir1 + +1. Not supported in multi-recipient mode + + Signing / MAC | Algorithm identifier(s) + :------------------------- | :------------------------------ + RSASSA-PKCS#1v1.5 | RS256, RS384, RS512 + RSASSA-PSS | PS256, PS384, PS512 + HMAC | HS256, HS384, HS512 + ECDSA | ES256, ES384, ES512 + Ed25519 | EdDSA2 + +2. Only available in version 2 of the package + + Content encryption | Algorithm identifier(s) + :------------------------- | :------------------------------ + AES-CBC+HMAC | A128CBC-HS256, A192CBC-HS384, A256CBC-HS512 + AES-GCM | A128GCM, A192GCM, A256GCM + + Compression | Algorithm identifiers(s) + :------------------------- | ------------------------------- + DEFLATE (RFC 1951) | DEF + +### Supported key types + +See below for a table of supported key types. These are understood by the +library, and can be passed to corresponding functions such as `NewEncrypter` or +`NewSigner`. Each of these keys can also be wrapped in a JWK if desired, which +allows attaching a key id. + + Algorithm(s) | Corresponding types + :------------------------- | ------------------------------- + RSA | *[rsa.PublicKey](https://pkg.go.dev/crypto/rsa/#PublicKey), *[rsa.PrivateKey](https://pkg.go.dev/crypto/rsa/#PrivateKey) + ECDH, ECDSA | *[ecdsa.PublicKey](https://pkg.go.dev/crypto/ecdsa/#PublicKey), *[ecdsa.PrivateKey](https://pkg.go.dev/crypto/ecdsa/#PrivateKey) + EdDSA1 | [ed25519.PublicKey](https://pkg.go.dev/crypto/ed25519#PublicKey), [ed25519.PrivateKey](https://pkg.go.dev/crypto/ed25519#PrivateKey) + AES, HMAC | []byte + +1. Only available in version 2 or later of the package + +## Examples + +[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v4.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v4) +[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v4/jwt.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v4/jwt) + +Examples can be found in the Godoc +reference for this package. The +[`jose-util`](https://github.com/go-jose/go-jose/tree/main/jose-util) +subdirectory also contains a small command-line utility which might be useful +as an example as well. diff --git a/vendor/github.com/go-jose/go-jose/v4/SECURITY.md b/vendor/github.com/go-jose/go-jose/v4/SECURITY.md new file mode 100644 index 00000000000..2f18a75a822 --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/SECURITY.md @@ -0,0 +1,13 @@ +# Security Policy +This document explains how to contact the Let's Encrypt security team to report security vulnerabilities. + +## Supported Versions +| Version | Supported | +| ------- | ----------| +| >= v3 | ✓ | +| v2 | ✗ | +| v1 | ✗ | + +## Reporting a vulnerability + +Please see [https://letsencrypt.org/contact/#security](https://letsencrypt.org/contact/#security) for the email address to report a vulnerability. Ensure that the subject line for your report contains the word `vulnerability` and is descriptive. Your email should be acknowledged within 24 hours. If you do not receive a response within 24 hours, please follow-up again with another email. diff --git a/vendor/github.com/go-jose/go-jose/v4/asymmetric.go b/vendor/github.com/go-jose/go-jose/v4/asymmetric.go new file mode 100644 index 00000000000..f8d5774ef56 --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/asymmetric.go @@ -0,0 +1,595 @@ +/*- + * Copyright 2014 Square Inc. + * + * 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 jose + +import ( + "crypto" + "crypto/aes" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/rand" + "crypto/rsa" + "crypto/sha1" + "crypto/sha256" + "errors" + "fmt" + "math/big" + + josecipher "github.com/go-jose/go-jose/v4/cipher" + "github.com/go-jose/go-jose/v4/json" +) + +// A generic RSA-based encrypter/verifier +type rsaEncrypterVerifier struct { + publicKey *rsa.PublicKey +} + +// A generic RSA-based decrypter/signer +type rsaDecrypterSigner struct { + privateKey *rsa.PrivateKey +} + +// A generic EC-based encrypter/verifier +type ecEncrypterVerifier struct { + publicKey *ecdsa.PublicKey +} + +type edEncrypterVerifier struct { + publicKey ed25519.PublicKey +} + +// A key generator for ECDH-ES +type ecKeyGenerator struct { + size int + algID string + publicKey *ecdsa.PublicKey +} + +// A generic EC-based decrypter/signer +type ecDecrypterSigner struct { + privateKey *ecdsa.PrivateKey +} + +type edDecrypterSigner struct { + privateKey ed25519.PrivateKey +} + +// newRSARecipient creates recipientKeyInfo based on the given key. +func newRSARecipient(keyAlg KeyAlgorithm, publicKey *rsa.PublicKey) (recipientKeyInfo, error) { + // Verify that key management algorithm is supported by this encrypter + switch keyAlg { + case RSA1_5, RSA_OAEP, RSA_OAEP_256: + default: + return recipientKeyInfo{}, ErrUnsupportedAlgorithm + } + + if publicKey == nil { + return recipientKeyInfo{}, errors.New("invalid public key") + } + + return recipientKeyInfo{ + keyAlg: keyAlg, + keyEncrypter: &rsaEncrypterVerifier{ + publicKey: publicKey, + }, + }, nil +} + +// newRSASigner creates a recipientSigInfo based on the given key. +func newRSASigner(sigAlg SignatureAlgorithm, privateKey *rsa.PrivateKey) (recipientSigInfo, error) { + // Verify that key management algorithm is supported by this encrypter + switch sigAlg { + case RS256, RS384, RS512, PS256, PS384, PS512: + default: + return recipientSigInfo{}, ErrUnsupportedAlgorithm + } + + if privateKey == nil { + return recipientSigInfo{}, errors.New("invalid private key") + } + + return recipientSigInfo{ + sigAlg: sigAlg, + publicKey: staticPublicKey(&JSONWebKey{ + Key: privateKey.Public(), + }), + signer: &rsaDecrypterSigner{ + privateKey: privateKey, + }, + }, nil +} + +func newEd25519Signer(sigAlg SignatureAlgorithm, privateKey ed25519.PrivateKey) (recipientSigInfo, error) { + if sigAlg != EdDSA { + return recipientSigInfo{}, ErrUnsupportedAlgorithm + } + + if privateKey == nil { + return recipientSigInfo{}, errors.New("invalid private key") + } + return recipientSigInfo{ + sigAlg: sigAlg, + publicKey: staticPublicKey(&JSONWebKey{ + Key: privateKey.Public(), + }), + signer: &edDecrypterSigner{ + privateKey: privateKey, + }, + }, nil +} + +// newECDHRecipient creates recipientKeyInfo based on the given key. +func newECDHRecipient(keyAlg KeyAlgorithm, publicKey *ecdsa.PublicKey) (recipientKeyInfo, error) { + // Verify that key management algorithm is supported by this encrypter + switch keyAlg { + case ECDH_ES, ECDH_ES_A128KW, ECDH_ES_A192KW, ECDH_ES_A256KW: + default: + return recipientKeyInfo{}, ErrUnsupportedAlgorithm + } + + if publicKey == nil || !publicKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) { + return recipientKeyInfo{}, errors.New("invalid public key") + } + + return recipientKeyInfo{ + keyAlg: keyAlg, + keyEncrypter: &ecEncrypterVerifier{ + publicKey: publicKey, + }, + }, nil +} + +// newECDSASigner creates a recipientSigInfo based on the given key. +func newECDSASigner(sigAlg SignatureAlgorithm, privateKey *ecdsa.PrivateKey) (recipientSigInfo, error) { + // Verify that key management algorithm is supported by this encrypter + switch sigAlg { + case ES256, ES384, ES512: + default: + return recipientSigInfo{}, ErrUnsupportedAlgorithm + } + + if privateKey == nil { + return recipientSigInfo{}, errors.New("invalid private key") + } + + return recipientSigInfo{ + sigAlg: sigAlg, + publicKey: staticPublicKey(&JSONWebKey{ + Key: privateKey.Public(), + }), + signer: &ecDecrypterSigner{ + privateKey: privateKey, + }, + }, nil +} + +// Encrypt the given payload and update the object. +func (ctx rsaEncrypterVerifier) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) { + encryptedKey, err := ctx.encrypt(cek, alg) + if err != nil { + return recipientInfo{}, err + } + + return recipientInfo{ + encryptedKey: encryptedKey, + header: &rawHeader{}, + }, nil +} + +// Encrypt the given payload. Based on the key encryption algorithm, +// this will either use RSA-PKCS1v1.5 or RSA-OAEP (with SHA-1 or SHA-256). +func (ctx rsaEncrypterVerifier) encrypt(cek []byte, alg KeyAlgorithm) ([]byte, error) { + switch alg { + case RSA1_5: + return rsa.EncryptPKCS1v15(RandReader, ctx.publicKey, cek) + case RSA_OAEP: + return rsa.EncryptOAEP(sha1.New(), RandReader, ctx.publicKey, cek, []byte{}) + case RSA_OAEP_256: + return rsa.EncryptOAEP(sha256.New(), RandReader, ctx.publicKey, cek, []byte{}) + } + + return nil, ErrUnsupportedAlgorithm +} + +// Decrypt the given payload and return the content encryption key. +func (ctx rsaDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) { + return ctx.decrypt(recipient.encryptedKey, headers.getAlgorithm(), generator) +} + +// Decrypt the given payload. Based on the key encryption algorithm, +// this will either use RSA-PKCS1v1.5 or RSA-OAEP (with SHA-1 or SHA-256). +func (ctx rsaDecrypterSigner) decrypt(jek []byte, alg KeyAlgorithm, generator keyGenerator) ([]byte, error) { + // Note: The random reader on decrypt operations is only used for blinding, + // so stubbing is meanlingless (hence the direct use of rand.Reader). + switch alg { + case RSA1_5: + defer func() { + // DecryptPKCS1v15SessionKey sometimes panics on an invalid payload + // because of an index out of bounds error, which we want to ignore. + // This has been fixed in Go 1.3.1 (released 2014/08/13), the recover() + // only exists for preventing crashes with unpatched versions. + // See: https://groups.google.com/forum/#!topic/golang-dev/7ihX6Y6kx9k + // See: https://code.google.com/p/go/source/detail?r=58ee390ff31602edb66af41ed10901ec95904d33 + _ = recover() + }() + + // Perform some input validation. + keyBytes := ctx.privateKey.PublicKey.N.BitLen() / 8 + if keyBytes != len(jek) { + // Input size is incorrect, the encrypted payload should always match + // the size of the public modulus (e.g. using a 2048 bit key will + // produce 256 bytes of output). Reject this since it's invalid input. + return nil, ErrCryptoFailure + } + + cek, _, err := generator.genKey() + if err != nil { + return nil, ErrCryptoFailure + } + + // When decrypting an RSA-PKCS1v1.5 payload, we must take precautions to + // prevent chosen-ciphertext attacks as described in RFC 3218, "Preventing + // the Million Message Attack on Cryptographic Message Syntax". We are + // therefore deliberately ignoring errors here. + _ = rsa.DecryptPKCS1v15SessionKey(rand.Reader, ctx.privateKey, jek, cek) + + return cek, nil + case RSA_OAEP: + // Use rand.Reader for RSA blinding + return rsa.DecryptOAEP(sha1.New(), rand.Reader, ctx.privateKey, jek, []byte{}) + case RSA_OAEP_256: + // Use rand.Reader for RSA blinding + return rsa.DecryptOAEP(sha256.New(), rand.Reader, ctx.privateKey, jek, []byte{}) + } + + return nil, ErrUnsupportedAlgorithm +} + +// Sign the given payload +func (ctx rsaDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) { + var hash crypto.Hash + + switch alg { + case RS256, PS256: + hash = crypto.SHA256 + case RS384, PS384: + hash = crypto.SHA384 + case RS512, PS512: + hash = crypto.SHA512 + default: + return Signature{}, ErrUnsupportedAlgorithm + } + + hasher := hash.New() + + // According to documentation, Write() on hash never fails + _, _ = hasher.Write(payload) + hashed := hasher.Sum(nil) + + var out []byte + var err error + + switch alg { + case RS256, RS384, RS512: + // TODO(https://github.com/go-jose/go-jose/issues/40): As of go1.20, the + // random parameter is legacy and ignored, and it can be nil. + // https://cs.opensource.google/go/go/+/refs/tags/go1.20:src/crypto/rsa/pkcs1v15.go;l=263;bpv=0;bpt=1 + out, err = rsa.SignPKCS1v15(RandReader, ctx.privateKey, hash, hashed) + case PS256, PS384, PS512: + out, err = rsa.SignPSS(RandReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthEqualsHash, + }) + } + + if err != nil { + return Signature{}, err + } + + return Signature{ + Signature: out, + protected: &rawHeader{}, + }, nil +} + +// Verify the given payload +func (ctx rsaEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error { + var hash crypto.Hash + + switch alg { + case RS256, PS256: + hash = crypto.SHA256 + case RS384, PS384: + hash = crypto.SHA384 + case RS512, PS512: + hash = crypto.SHA512 + default: + return ErrUnsupportedAlgorithm + } + + hasher := hash.New() + + // According to documentation, Write() on hash never fails + _, _ = hasher.Write(payload) + hashed := hasher.Sum(nil) + + switch alg { + case RS256, RS384, RS512: + return rsa.VerifyPKCS1v15(ctx.publicKey, hash, hashed, signature) + case PS256, PS384, PS512: + return rsa.VerifyPSS(ctx.publicKey, hash, hashed, signature, nil) + } + + return ErrUnsupportedAlgorithm +} + +// Encrypt the given payload and update the object. +func (ctx ecEncrypterVerifier) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) { + switch alg { + case ECDH_ES: + // ECDH-ES mode doesn't wrap a key, the shared secret is used directly as the key. + return recipientInfo{ + header: &rawHeader{}, + }, nil + case ECDH_ES_A128KW, ECDH_ES_A192KW, ECDH_ES_A256KW: + default: + return recipientInfo{}, ErrUnsupportedAlgorithm + } + + generator := ecKeyGenerator{ + algID: string(alg), + publicKey: ctx.publicKey, + } + + switch alg { + case ECDH_ES_A128KW: + generator.size = 16 + case ECDH_ES_A192KW: + generator.size = 24 + case ECDH_ES_A256KW: + generator.size = 32 + } + + kek, header, err := generator.genKey() + if err != nil { + return recipientInfo{}, err + } + + block, err := aes.NewCipher(kek) + if err != nil { + return recipientInfo{}, err + } + + jek, err := josecipher.KeyWrap(block, cek) + if err != nil { + return recipientInfo{}, err + } + + return recipientInfo{ + encryptedKey: jek, + header: &header, + }, nil +} + +// Get key size for EC key generator +func (ctx ecKeyGenerator) keySize() int { + return ctx.size +} + +// Get a content encryption key for ECDH-ES +func (ctx ecKeyGenerator) genKey() ([]byte, rawHeader, error) { + priv, err := ecdsa.GenerateKey(ctx.publicKey.Curve, RandReader) + if err != nil { + return nil, rawHeader{}, err + } + + out := josecipher.DeriveECDHES(ctx.algID, []byte{}, []byte{}, priv, ctx.publicKey, ctx.size) + + b, err := json.Marshal(&JSONWebKey{ + Key: &priv.PublicKey, + }) + if err != nil { + return nil, nil, err + } + + headers := rawHeader{ + headerEPK: makeRawMessage(b), + } + + return out, headers, nil +} + +// Decrypt the given payload and return the content encryption key. +func (ctx ecDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) { + epk, err := headers.getEPK() + if err != nil { + return nil, errors.New("go-jose/go-jose: invalid epk header") + } + if epk == nil { + return nil, errors.New("go-jose/go-jose: missing epk header") + } + + publicKey, ok := epk.Key.(*ecdsa.PublicKey) + if publicKey == nil || !ok { + return nil, errors.New("go-jose/go-jose: invalid epk header") + } + + if !ctx.privateKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) { + return nil, errors.New("go-jose/go-jose: invalid public key in epk header") + } + + apuData, err := headers.getAPU() + if err != nil { + return nil, errors.New("go-jose/go-jose: invalid apu header") + } + apvData, err := headers.getAPV() + if err != nil { + return nil, errors.New("go-jose/go-jose: invalid apv header") + } + + deriveKey := func(algID string, size int) []byte { + return josecipher.DeriveECDHES(algID, apuData.bytes(), apvData.bytes(), ctx.privateKey, publicKey, size) + } + + var keySize int + + algorithm := headers.getAlgorithm() + switch algorithm { + case ECDH_ES: + // ECDH-ES uses direct key agreement, no key unwrapping necessary. + return deriveKey(string(headers.getEncryption()), generator.keySize()), nil + case ECDH_ES_A128KW: + keySize = 16 + case ECDH_ES_A192KW: + keySize = 24 + case ECDH_ES_A256KW: + keySize = 32 + default: + return nil, ErrUnsupportedAlgorithm + } + + key := deriveKey(string(algorithm), keySize) + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + return josecipher.KeyUnwrap(block, recipient.encryptedKey) +} + +func (ctx edDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) { + if alg != EdDSA { + return Signature{}, ErrUnsupportedAlgorithm + } + + sig, err := ctx.privateKey.Sign(RandReader, payload, crypto.Hash(0)) + if err != nil { + return Signature{}, err + } + + return Signature{ + Signature: sig, + protected: &rawHeader{}, + }, nil +} + +func (ctx edEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error { + if alg != EdDSA { + return ErrUnsupportedAlgorithm + } + ok := ed25519.Verify(ctx.publicKey, payload, signature) + if !ok { + return errors.New("go-jose/go-jose: ed25519 signature failed to verify") + } + return nil +} + +// Sign the given payload +func (ctx ecDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) { + var expectedBitSize int + var hash crypto.Hash + + switch alg { + case ES256: + expectedBitSize = 256 + hash = crypto.SHA256 + case ES384: + expectedBitSize = 384 + hash = crypto.SHA384 + case ES512: + expectedBitSize = 521 + hash = crypto.SHA512 + } + + curveBits := ctx.privateKey.Curve.Params().BitSize + if expectedBitSize != curveBits { + return Signature{}, fmt.Errorf("go-jose/go-jose: expected %d bit key, got %d bits instead", expectedBitSize, curveBits) + } + + hasher := hash.New() + + // According to documentation, Write() on hash never fails + _, _ = hasher.Write(payload) + hashed := hasher.Sum(nil) + + r, s, err := ecdsa.Sign(RandReader, ctx.privateKey, hashed) + if err != nil { + return Signature{}, err + } + + keyBytes := curveBits / 8 + if curveBits%8 > 0 { + keyBytes++ + } + + // We serialize the outputs (r and s) into big-endian byte arrays and pad + // them with zeros on the left to make sure the sizes work out. Both arrays + // must be keyBytes long, and the output must be 2*keyBytes long. + rBytes := r.Bytes() + rBytesPadded := make([]byte, keyBytes) + copy(rBytesPadded[keyBytes-len(rBytes):], rBytes) + + sBytes := s.Bytes() + sBytesPadded := make([]byte, keyBytes) + copy(sBytesPadded[keyBytes-len(sBytes):], sBytes) + + out := append(rBytesPadded, sBytesPadded...) + + return Signature{ + Signature: out, + protected: &rawHeader{}, + }, nil +} + +// Verify the given payload +func (ctx ecEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error { + var keySize int + var hash crypto.Hash + + switch alg { + case ES256: + keySize = 32 + hash = crypto.SHA256 + case ES384: + keySize = 48 + hash = crypto.SHA384 + case ES512: + keySize = 66 + hash = crypto.SHA512 + default: + return ErrUnsupportedAlgorithm + } + + if len(signature) != 2*keySize { + return fmt.Errorf("go-jose/go-jose: invalid signature size, have %d bytes, wanted %d", len(signature), 2*keySize) + } + + hasher := hash.New() + + // According to documentation, Write() on hash never fails + _, _ = hasher.Write(payload) + hashed := hasher.Sum(nil) + + r := big.NewInt(0).SetBytes(signature[:keySize]) + s := big.NewInt(0).SetBytes(signature[keySize:]) + + match := ecdsa.Verify(ctx.publicKey, hashed, r, s) + if !match { + return errors.New("go-jose/go-jose: ecdsa signature failed to verify") + } + + return nil +} diff --git a/vendor/github.com/go-jose/go-jose/v4/cipher/cbc_hmac.go b/vendor/github.com/go-jose/go-jose/v4/cipher/cbc_hmac.go new file mode 100644 index 00000000000..af029cec0ba --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/cipher/cbc_hmac.go @@ -0,0 +1,196 @@ +/*- + * Copyright 2014 Square Inc. + * + * 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 josecipher + +import ( + "bytes" + "crypto/cipher" + "crypto/hmac" + "crypto/sha256" + "crypto/sha512" + "crypto/subtle" + "encoding/binary" + "errors" + "hash" +) + +const ( + nonceBytes = 16 +) + +// NewCBCHMAC instantiates a new AEAD based on CBC+HMAC. +func NewCBCHMAC(key []byte, newBlockCipher func([]byte) (cipher.Block, error)) (cipher.AEAD, error) { + keySize := len(key) / 2 + integrityKey := key[:keySize] + encryptionKey := key[keySize:] + + blockCipher, err := newBlockCipher(encryptionKey) + if err != nil { + return nil, err + } + + var hash func() hash.Hash + switch keySize { + case 16: + hash = sha256.New + case 24: + hash = sha512.New384 + case 32: + hash = sha512.New + } + + return &cbcAEAD{ + hash: hash, + blockCipher: blockCipher, + authtagBytes: keySize, + integrityKey: integrityKey, + }, nil +} + +// An AEAD based on CBC+HMAC +type cbcAEAD struct { + hash func() hash.Hash + authtagBytes int + integrityKey []byte + blockCipher cipher.Block +} + +func (ctx *cbcAEAD) NonceSize() int { + return nonceBytes +} + +func (ctx *cbcAEAD) Overhead() int { + // Maximum overhead is block size (for padding) plus auth tag length, where + // the length of the auth tag is equivalent to the key size. + return ctx.blockCipher.BlockSize() + ctx.authtagBytes +} + +// Seal encrypts and authenticates the plaintext. +func (ctx *cbcAEAD) Seal(dst, nonce, plaintext, data []byte) []byte { + // Output buffer -- must take care not to mangle plaintext input. + ciphertext := make([]byte, uint64(len(plaintext))+uint64(ctx.Overhead()))[:len(plaintext)] + copy(ciphertext, plaintext) + ciphertext = padBuffer(ciphertext, ctx.blockCipher.BlockSize()) + + cbc := cipher.NewCBCEncrypter(ctx.blockCipher, nonce) + + cbc.CryptBlocks(ciphertext, ciphertext) + authtag := ctx.computeAuthTag(data, nonce, ciphertext) + + ret, out := resize(dst, uint64(len(dst))+uint64(len(ciphertext))+uint64(len(authtag))) + copy(out, ciphertext) + copy(out[len(ciphertext):], authtag) + + return ret +} + +// Open decrypts and authenticates the ciphertext. +func (ctx *cbcAEAD) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { + if len(ciphertext) < ctx.authtagBytes { + return nil, errors.New("go-jose/go-jose: invalid ciphertext (too short)") + } + + offset := len(ciphertext) - ctx.authtagBytes + expectedTag := ctx.computeAuthTag(data, nonce, ciphertext[:offset]) + match := subtle.ConstantTimeCompare(expectedTag, ciphertext[offset:]) + if match != 1 { + return nil, errors.New("go-jose/go-jose: invalid ciphertext (auth tag mismatch)") + } + + cbc := cipher.NewCBCDecrypter(ctx.blockCipher, nonce) + + // Make copy of ciphertext buffer, don't want to modify in place + buffer := append([]byte{}, ciphertext[:offset]...) + + if len(buffer)%ctx.blockCipher.BlockSize() > 0 { + return nil, errors.New("go-jose/go-jose: invalid ciphertext (invalid length)") + } + + cbc.CryptBlocks(buffer, buffer) + + // Remove padding + plaintext, err := unpadBuffer(buffer, ctx.blockCipher.BlockSize()) + if err != nil { + return nil, err + } + + ret, out := resize(dst, uint64(len(dst))+uint64(len(plaintext))) + copy(out, plaintext) + + return ret, nil +} + +// Compute an authentication tag +func (ctx *cbcAEAD) computeAuthTag(aad, nonce, ciphertext []byte) []byte { + buffer := make([]byte, uint64(len(aad))+uint64(len(nonce))+uint64(len(ciphertext))+8) + n := 0 + n += copy(buffer, aad) + n += copy(buffer[n:], nonce) + n += copy(buffer[n:], ciphertext) + binary.BigEndian.PutUint64(buffer[n:], uint64(len(aad))*8) + + // According to documentation, Write() on hash.Hash never fails. + hmac := hmac.New(ctx.hash, ctx.integrityKey) + _, _ = hmac.Write(buffer) + + return hmac.Sum(nil)[:ctx.authtagBytes] +} + +// resize ensures that the given slice has a capacity of at least n bytes. +// If the capacity of the slice is less than n, a new slice is allocated +// and the existing data will be copied. +func resize(in []byte, n uint64) (head, tail []byte) { + if uint64(cap(in)) >= n { + head = in[:n] + } else { + head = make([]byte, n) + copy(head, in) + } + + tail = head[len(in):] + return +} + +// Apply padding +func padBuffer(buffer []byte, blockSize int) []byte { + missing := blockSize - (len(buffer) % blockSize) + ret, out := resize(buffer, uint64(len(buffer))+uint64(missing)) + padding := bytes.Repeat([]byte{byte(missing)}, missing) + copy(out, padding) + return ret +} + +// Remove padding +func unpadBuffer(buffer []byte, blockSize int) ([]byte, error) { + if len(buffer)%blockSize != 0 { + return nil, errors.New("go-jose/go-jose: invalid padding") + } + + last := buffer[len(buffer)-1] + count := int(last) + + if count == 0 || count > blockSize || count > len(buffer) { + return nil, errors.New("go-jose/go-jose: invalid padding") + } + + padding := bytes.Repeat([]byte{last}, count) + if !bytes.HasSuffix(buffer, padding) { + return nil, errors.New("go-jose/go-jose: invalid padding") + } + + return buffer[:len(buffer)-count], nil +} diff --git a/vendor/github.com/go-jose/go-jose/v4/cipher/concat_kdf.go b/vendor/github.com/go-jose/go-jose/v4/cipher/concat_kdf.go new file mode 100644 index 00000000000..f62c3bdba5d --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/cipher/concat_kdf.go @@ -0,0 +1,75 @@ +/*- + * Copyright 2014 Square Inc. + * + * 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 josecipher + +import ( + "crypto" + "encoding/binary" + "hash" + "io" +) + +type concatKDF struct { + z, info []byte + i uint32 + cache []byte + hasher hash.Hash +} + +// NewConcatKDF builds a KDF reader based on the given inputs. +func NewConcatKDF(hash crypto.Hash, z, algID, ptyUInfo, ptyVInfo, supPubInfo, supPrivInfo []byte) io.Reader { + buffer := make([]byte, uint64(len(algID))+uint64(len(ptyUInfo))+uint64(len(ptyVInfo))+uint64(len(supPubInfo))+uint64(len(supPrivInfo))) + n := 0 + n += copy(buffer, algID) + n += copy(buffer[n:], ptyUInfo) + n += copy(buffer[n:], ptyVInfo) + n += copy(buffer[n:], supPubInfo) + copy(buffer[n:], supPrivInfo) + + hasher := hash.New() + + return &concatKDF{ + z: z, + info: buffer, + hasher: hasher, + cache: []byte{}, + i: 1, + } +} + +func (ctx *concatKDF) Read(out []byte) (int, error) { + copied := copy(out, ctx.cache) + ctx.cache = ctx.cache[copied:] + + for copied < len(out) { + ctx.hasher.Reset() + + // Write on a hash.Hash never fails + _ = binary.Write(ctx.hasher, binary.BigEndian, ctx.i) + _, _ = ctx.hasher.Write(ctx.z) + _, _ = ctx.hasher.Write(ctx.info) + + hash := ctx.hasher.Sum(nil) + chunkCopied := copy(out[copied:], hash) + copied += chunkCopied + ctx.cache = hash[chunkCopied:] + + ctx.i++ + } + + return copied, nil +} diff --git a/vendor/github.com/go-jose/go-jose/v4/cipher/ecdh_es.go b/vendor/github.com/go-jose/go-jose/v4/cipher/ecdh_es.go new file mode 100644 index 00000000000..093c646740b --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/cipher/ecdh_es.go @@ -0,0 +1,86 @@ +/*- + * Copyright 2014 Square Inc. + * + * 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 josecipher + +import ( + "bytes" + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "encoding/binary" +) + +// DeriveECDHES derives a shared encryption key using ECDH/ConcatKDF as described in JWE/JWA. +// It is an error to call this function with a private/public key that are not on the same +// curve. Callers must ensure that the keys are valid before calling this function. Output +// size may be at most 1<<16 bytes (64 KiB). +func DeriveECDHES(alg string, apuData, apvData []byte, priv *ecdsa.PrivateKey, pub *ecdsa.PublicKey, size int) []byte { + if size > 1<<16 { + panic("ECDH-ES output size too large, must be less than or equal to 1<<16") + } + + // algId, partyUInfo, partyVInfo inputs must be prefixed with the length + algID := lengthPrefixed([]byte(alg)) + ptyUInfo := lengthPrefixed(apuData) + ptyVInfo := lengthPrefixed(apvData) + + // suppPubInfo is the encoded length of the output size in bits + supPubInfo := make([]byte, 4) + binary.BigEndian.PutUint32(supPubInfo, uint32(size)*8) + + if !priv.PublicKey.Curve.IsOnCurve(pub.X, pub.Y) { + panic("public key not on same curve as private key") + } + + z, _ := priv.Curve.ScalarMult(pub.X, pub.Y, priv.D.Bytes()) + zBytes := z.Bytes() + + // Note that calling z.Bytes() on a big.Int may strip leading zero bytes from + // the returned byte array. This can lead to a problem where zBytes will be + // shorter than expected which breaks the key derivation. Therefore we must pad + // to the full length of the expected coordinate here before calling the KDF. + octSize := dSize(priv.Curve) + if len(zBytes) != octSize { + zBytes = append(bytes.Repeat([]byte{0}, octSize-len(zBytes)), zBytes...) + } + + reader := NewConcatKDF(crypto.SHA256, zBytes, algID, ptyUInfo, ptyVInfo, supPubInfo, []byte{}) + key := make([]byte, size) + + // Read on the KDF will never fail + _, _ = reader.Read(key) + + return key +} + +// dSize returns the size in octets for a coordinate on a elliptic curve. +func dSize(curve elliptic.Curve) int { + order := curve.Params().P + bitLen := order.BitLen() + size := bitLen / 8 + if bitLen%8 != 0 { + size++ + } + return size +} + +func lengthPrefixed(data []byte) []byte { + out := make([]byte, len(data)+4) + binary.BigEndian.PutUint32(out, uint32(len(data))) + copy(out[4:], data) + return out +} diff --git a/vendor/github.com/go-jose/go-jose/v4/cipher/key_wrap.go b/vendor/github.com/go-jose/go-jose/v4/cipher/key_wrap.go new file mode 100644 index 00000000000..b9effbca8a4 --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/cipher/key_wrap.go @@ -0,0 +1,109 @@ +/*- + * Copyright 2014 Square Inc. + * + * 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 josecipher + +import ( + "crypto/cipher" + "crypto/subtle" + "encoding/binary" + "errors" +) + +var defaultIV = []byte{0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6} + +// KeyWrap implements NIST key wrapping; it wraps a content encryption key (cek) with the given block cipher. +func KeyWrap(block cipher.Block, cek []byte) ([]byte, error) { + if len(cek)%8 != 0 { + return nil, errors.New("go-jose/go-jose: key wrap input must be 8 byte blocks") + } + + n := len(cek) / 8 + r := make([][]byte, n) + + for i := range r { + r[i] = make([]byte, 8) + copy(r[i], cek[i*8:]) + } + + buffer := make([]byte, 16) + tBytes := make([]byte, 8) + copy(buffer, defaultIV) + + for t := 0; t < 6*n; t++ { + copy(buffer[8:], r[t%n]) + + block.Encrypt(buffer, buffer) + + binary.BigEndian.PutUint64(tBytes, uint64(t+1)) + + for i := 0; i < 8; i++ { + buffer[i] ^= tBytes[i] + } + copy(r[t%n], buffer[8:]) + } + + out := make([]byte, (n+1)*8) + copy(out, buffer[:8]) + for i := range r { + copy(out[(i+1)*8:], r[i]) + } + + return out, nil +} + +// KeyUnwrap implements NIST key unwrapping; it unwraps a content encryption key (cek) with the given block cipher. +func KeyUnwrap(block cipher.Block, ciphertext []byte) ([]byte, error) { + if len(ciphertext)%8 != 0 { + return nil, errors.New("go-jose/go-jose: key wrap input must be 8 byte blocks") + } + + n := (len(ciphertext) / 8) - 1 + r := make([][]byte, n) + + for i := range r { + r[i] = make([]byte, 8) + copy(r[i], ciphertext[(i+1)*8:]) + } + + buffer := make([]byte, 16) + tBytes := make([]byte, 8) + copy(buffer[:8], ciphertext[:8]) + + for t := 6*n - 1; t >= 0; t-- { + binary.BigEndian.PutUint64(tBytes, uint64(t+1)) + + for i := 0; i < 8; i++ { + buffer[i] ^= tBytes[i] + } + copy(buffer[8:], r[t%n]) + + block.Decrypt(buffer, buffer) + + copy(r[t%n], buffer[8:]) + } + + if subtle.ConstantTimeCompare(buffer[:8], defaultIV) == 0 { + return nil, errors.New("go-jose/go-jose: failed to unwrap key") + } + + out := make([]byte, n*8) + for i := range r { + copy(out[i*8:], r[i]) + } + + return out, nil +} diff --git a/vendor/github.com/go-jose/go-jose/v4/crypter.go b/vendor/github.com/go-jose/go-jose/v4/crypter.go new file mode 100644 index 00000000000..d81b03b4474 --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/crypter.go @@ -0,0 +1,599 @@ +/*- + * Copyright 2014 Square Inc. + * + * 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 jose + +import ( + "crypto/ecdsa" + "crypto/rsa" + "errors" + "fmt" + + "github.com/go-jose/go-jose/v4/json" +) + +// Encrypter represents an encrypter which produces an encrypted JWE object. +type Encrypter interface { + Encrypt(plaintext []byte) (*JSONWebEncryption, error) + EncryptWithAuthData(plaintext []byte, aad []byte) (*JSONWebEncryption, error) + Options() EncrypterOptions +} + +// A generic content cipher +type contentCipher interface { + keySize() int + encrypt(cek []byte, aad, plaintext []byte) (*aeadParts, error) + decrypt(cek []byte, aad []byte, parts *aeadParts) ([]byte, error) +} + +// A key generator (for generating/getting a CEK) +type keyGenerator interface { + keySize() int + genKey() ([]byte, rawHeader, error) +} + +// A generic key encrypter +type keyEncrypter interface { + encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) // Encrypt a key +} + +// A generic key decrypter +type keyDecrypter interface { + decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) // Decrypt a key +} + +// A generic encrypter based on the given key encrypter and content cipher. +type genericEncrypter struct { + contentAlg ContentEncryption + compressionAlg CompressionAlgorithm + cipher contentCipher + recipients []recipientKeyInfo + keyGenerator keyGenerator + extraHeaders map[HeaderKey]interface{} +} + +type recipientKeyInfo struct { + keyID string + keyAlg KeyAlgorithm + keyEncrypter keyEncrypter +} + +// EncrypterOptions represents options that can be set on new encrypters. +type EncrypterOptions struct { + Compression CompressionAlgorithm + + // Optional map of name/value pairs to be inserted into the protected + // header of a JWS object. Some specifications which make use of + // JWS require additional values here. + // + // Values will be serialized by [json.Marshal] and must be valid inputs to + // that function. + // + // [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal + ExtraHeaders map[HeaderKey]interface{} +} + +// WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it +// if necessary, and returns the updated EncrypterOptions. +// +// The v parameter will be serialized by [json.Marshal] and must be a valid +// input to that function. +// +// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal +func (eo *EncrypterOptions) WithHeader(k HeaderKey, v interface{}) *EncrypterOptions { + if eo.ExtraHeaders == nil { + eo.ExtraHeaders = map[HeaderKey]interface{}{} + } + eo.ExtraHeaders[k] = v + return eo +} + +// WithContentType adds a content type ("cty") header and returns the updated +// EncrypterOptions. +func (eo *EncrypterOptions) WithContentType(contentType ContentType) *EncrypterOptions { + return eo.WithHeader(HeaderContentType, contentType) +} + +// WithType adds a type ("typ") header and returns the updated EncrypterOptions. +func (eo *EncrypterOptions) WithType(typ ContentType) *EncrypterOptions { + return eo.WithHeader(HeaderType, typ) +} + +// Recipient represents an algorithm/key to encrypt messages to. +// +// PBES2Count and PBES2Salt correspond with the "p2c" and "p2s" headers used +// on the password-based encryption algorithms PBES2-HS256+A128KW, +// PBES2-HS384+A192KW, and PBES2-HS512+A256KW. If they are not provided a safe +// default of 100000 will be used for the count and a 128-bit random salt will +// be generated. +type Recipient struct { + Algorithm KeyAlgorithm + // Key must have one of these types: + // - ed25519.PublicKey + // - *ecdsa.PublicKey + // - *rsa.PublicKey + // - *JSONWebKey + // - JSONWebKey + // - []byte (a symmetric key) + // - Any type that satisfies the OpaqueKeyEncrypter interface + // + // The type of Key must match the value of Algorithm. + Key interface{} + KeyID string + PBES2Count int + PBES2Salt []byte +} + +// NewEncrypter creates an appropriate encrypter based on the key type +func NewEncrypter(enc ContentEncryption, rcpt Recipient, opts *EncrypterOptions) (Encrypter, error) { + encrypter := &genericEncrypter{ + contentAlg: enc, + recipients: []recipientKeyInfo{}, + cipher: getContentCipher(enc), + } + if opts != nil { + encrypter.compressionAlg = opts.Compression + encrypter.extraHeaders = opts.ExtraHeaders + } + + if encrypter.cipher == nil { + return nil, ErrUnsupportedAlgorithm + } + + var keyID string + var rawKey interface{} + switch encryptionKey := rcpt.Key.(type) { + case JSONWebKey: + keyID, rawKey = encryptionKey.KeyID, encryptionKey.Key + case *JSONWebKey: + keyID, rawKey = encryptionKey.KeyID, encryptionKey.Key + case OpaqueKeyEncrypter: + keyID, rawKey = encryptionKey.KeyID(), encryptionKey + default: + rawKey = encryptionKey + } + + switch rcpt.Algorithm { + case DIRECT: + // Direct encryption mode must be treated differently + keyBytes, ok := rawKey.([]byte) + if !ok { + return nil, ErrUnsupportedKeyType + } + if encrypter.cipher.keySize() != len(keyBytes) { + return nil, ErrInvalidKeySize + } + encrypter.keyGenerator = staticKeyGenerator{ + key: keyBytes, + } + recipientInfo, _ := newSymmetricRecipient(rcpt.Algorithm, keyBytes) + recipientInfo.keyID = keyID + if rcpt.KeyID != "" { + recipientInfo.keyID = rcpt.KeyID + } + encrypter.recipients = []recipientKeyInfo{recipientInfo} + return encrypter, nil + case ECDH_ES: + // ECDH-ES (w/o key wrapping) is similar to DIRECT mode + keyDSA, ok := rawKey.(*ecdsa.PublicKey) + if !ok { + return nil, ErrUnsupportedKeyType + } + encrypter.keyGenerator = ecKeyGenerator{ + size: encrypter.cipher.keySize(), + algID: string(enc), + publicKey: keyDSA, + } + recipientInfo, _ := newECDHRecipient(rcpt.Algorithm, keyDSA) + recipientInfo.keyID = keyID + if rcpt.KeyID != "" { + recipientInfo.keyID = rcpt.KeyID + } + encrypter.recipients = []recipientKeyInfo{recipientInfo} + return encrypter, nil + default: + // Can just add a standard recipient + encrypter.keyGenerator = randomKeyGenerator{ + size: encrypter.cipher.keySize(), + } + err := encrypter.addRecipient(rcpt) + return encrypter, err + } +} + +// NewMultiEncrypter creates a multi-encrypter based on the given parameters +func NewMultiEncrypter(enc ContentEncryption, rcpts []Recipient, opts *EncrypterOptions) (Encrypter, error) { + cipher := getContentCipher(enc) + + if cipher == nil { + return nil, ErrUnsupportedAlgorithm + } + if len(rcpts) == 0 { + return nil, fmt.Errorf("go-jose/go-jose: recipients is nil or empty") + } + + encrypter := &genericEncrypter{ + contentAlg: enc, + recipients: []recipientKeyInfo{}, + cipher: cipher, + keyGenerator: randomKeyGenerator{ + size: cipher.keySize(), + }, + } + + if opts != nil { + encrypter.compressionAlg = opts.Compression + encrypter.extraHeaders = opts.ExtraHeaders + } + + for _, recipient := range rcpts { + err := encrypter.addRecipient(recipient) + if err != nil { + return nil, err + } + } + + return encrypter, nil +} + +func (ctx *genericEncrypter) addRecipient(recipient Recipient) (err error) { + var recipientInfo recipientKeyInfo + + switch recipient.Algorithm { + case DIRECT, ECDH_ES: + return fmt.Errorf("go-jose/go-jose: key algorithm '%s' not supported in multi-recipient mode", recipient.Algorithm) + } + + recipientInfo, err = makeJWERecipient(recipient.Algorithm, recipient.Key) + if recipient.KeyID != "" { + recipientInfo.keyID = recipient.KeyID + } + + switch recipient.Algorithm { + case PBES2_HS256_A128KW, PBES2_HS384_A192KW, PBES2_HS512_A256KW: + if sr, ok := recipientInfo.keyEncrypter.(*symmetricKeyCipher); ok { + sr.p2c = recipient.PBES2Count + sr.p2s = recipient.PBES2Salt + } + } + + if err == nil { + ctx.recipients = append(ctx.recipients, recipientInfo) + } + return err +} + +func makeJWERecipient(alg KeyAlgorithm, encryptionKey interface{}) (recipientKeyInfo, error) { + switch encryptionKey := encryptionKey.(type) { + case *rsa.PublicKey: + return newRSARecipient(alg, encryptionKey) + case *ecdsa.PublicKey: + return newECDHRecipient(alg, encryptionKey) + case []byte: + return newSymmetricRecipient(alg, encryptionKey) + case string: + return newSymmetricRecipient(alg, []byte(encryptionKey)) + case *JSONWebKey: + recipient, err := makeJWERecipient(alg, encryptionKey.Key) + recipient.keyID = encryptionKey.KeyID + return recipient, err + case OpaqueKeyEncrypter: + return newOpaqueKeyEncrypter(alg, encryptionKey) + } + return recipientKeyInfo{}, ErrUnsupportedKeyType +} + +// newDecrypter creates an appropriate decrypter based on the key type +func newDecrypter(decryptionKey interface{}) (keyDecrypter, error) { + switch decryptionKey := decryptionKey.(type) { + case *rsa.PrivateKey: + return &rsaDecrypterSigner{ + privateKey: decryptionKey, + }, nil + case *ecdsa.PrivateKey: + return &ecDecrypterSigner{ + privateKey: decryptionKey, + }, nil + case []byte: + return &symmetricKeyCipher{ + key: decryptionKey, + }, nil + case string: + return &symmetricKeyCipher{ + key: []byte(decryptionKey), + }, nil + case JSONWebKey: + return newDecrypter(decryptionKey.Key) + case *JSONWebKey: + return newDecrypter(decryptionKey.Key) + case OpaqueKeyDecrypter: + return &opaqueKeyDecrypter{decrypter: decryptionKey}, nil + default: + return nil, ErrUnsupportedKeyType + } +} + +// Implementation of encrypt method producing a JWE object. +func (ctx *genericEncrypter) Encrypt(plaintext []byte) (*JSONWebEncryption, error) { + return ctx.EncryptWithAuthData(plaintext, nil) +} + +// Implementation of encrypt method producing a JWE object. +func (ctx *genericEncrypter) EncryptWithAuthData(plaintext, aad []byte) (*JSONWebEncryption, error) { + obj := &JSONWebEncryption{} + obj.aad = aad + + obj.protected = &rawHeader{} + err := obj.protected.set(headerEncryption, ctx.contentAlg) + if err != nil { + return nil, err + } + + obj.recipients = make([]recipientInfo, len(ctx.recipients)) + + if len(ctx.recipients) == 0 { + return nil, fmt.Errorf("go-jose/go-jose: no recipients to encrypt to") + } + + cek, headers, err := ctx.keyGenerator.genKey() + if err != nil { + return nil, err + } + + obj.protected.merge(&headers) + + for i, info := range ctx.recipients { + recipient, err := info.keyEncrypter.encryptKey(cek, info.keyAlg) + if err != nil { + return nil, err + } + + err = recipient.header.set(headerAlgorithm, info.keyAlg) + if err != nil { + return nil, err + } + + if info.keyID != "" { + err = recipient.header.set(headerKeyID, info.keyID) + if err != nil { + return nil, err + } + } + obj.recipients[i] = recipient + } + + if len(ctx.recipients) == 1 { + // Move per-recipient headers into main protected header if there's + // only a single recipient. + obj.protected.merge(obj.recipients[0].header) + obj.recipients[0].header = nil + } + + if ctx.compressionAlg != NONE { + plaintext, err = compress(ctx.compressionAlg, plaintext) + if err != nil { + return nil, err + } + + err = obj.protected.set(headerCompression, ctx.compressionAlg) + if err != nil { + return nil, err + } + } + + for k, v := range ctx.extraHeaders { + b, err := json.Marshal(v) + if err != nil { + return nil, err + } + (*obj.protected)[k] = makeRawMessage(b) + } + + authData := obj.computeAuthData() + parts, err := ctx.cipher.encrypt(cek, authData, plaintext) + if err != nil { + return nil, err + } + + obj.iv = parts.iv + obj.ciphertext = parts.ciphertext + obj.tag = parts.tag + + return obj, nil +} + +func (ctx *genericEncrypter) Options() EncrypterOptions { + return EncrypterOptions{ + Compression: ctx.compressionAlg, + ExtraHeaders: ctx.extraHeaders, + } +} + +// Decrypt and validate the object and return the plaintext. This +// function does not support multi-recipient. If you desire multi-recipient +// decryption use DecryptMulti instead. +// +// The decryptionKey argument must contain a private or symmetric key +// and must have one of these types: +// - *ecdsa.PrivateKey +// - *rsa.PrivateKey +// - *JSONWebKey +// - JSONWebKey +// - *JSONWebKeySet +// - JSONWebKeySet +// - []byte (a symmetric key) +// - string (a symmetric key) +// - Any type that satisfies the OpaqueKeyDecrypter interface. +// +// Note that ed25519 is only available for signatures, not encryption, so is +// not an option here. +// +// Automatically decompresses plaintext, but returns an error if the decompressed +// data would be >250kB or >10x the size of the compressed data, whichever is larger. +func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error) { + headers := obj.mergedHeaders(nil) + + if len(obj.recipients) > 1 { + return nil, errors.New("go-jose/go-jose: too many recipients in payload; expecting only one") + } + + critical, err := headers.getCritical() + if err != nil { + return nil, fmt.Errorf("go-jose/go-jose: invalid crit header") + } + + if len(critical) > 0 { + return nil, fmt.Errorf("go-jose/go-jose: unsupported crit header") + } + + key, err := tryJWKS(decryptionKey, obj.Header) + if err != nil { + return nil, err + } + decrypter, err := newDecrypter(key) + if err != nil { + return nil, err + } + + cipher := getContentCipher(headers.getEncryption()) + if cipher == nil { + return nil, fmt.Errorf("go-jose/go-jose: unsupported enc value '%s'", string(headers.getEncryption())) + } + + generator := randomKeyGenerator{ + size: cipher.keySize(), + } + + parts := &aeadParts{ + iv: obj.iv, + ciphertext: obj.ciphertext, + tag: obj.tag, + } + + authData := obj.computeAuthData() + + var plaintext []byte + recipient := obj.recipients[0] + recipientHeaders := obj.mergedHeaders(&recipient) + + cek, err := decrypter.decryptKey(recipientHeaders, &recipient, generator) + if err == nil { + // Found a valid CEK -- let's try to decrypt. + plaintext, err = cipher.decrypt(cek, authData, parts) + } + + if plaintext == nil { + return nil, ErrCryptoFailure + } + + // The "zip" header parameter may only be present in the protected header. + if comp := obj.protected.getCompression(); comp != "" { + plaintext, err = decompress(comp, plaintext) + if err != nil { + return nil, fmt.Errorf("go-jose/go-jose: failed to decompress plaintext: %v", err) + } + } + + return plaintext, nil +} + +// DecryptMulti decrypts and validates the object and returns the plaintexts, +// with support for multiple recipients. It returns the index of the recipient +// for which the decryption was successful, the merged headers for that recipient, +// and the plaintext. +// +// The decryptionKey argument must have one of the types allowed for the +// decryptionKey argument of Decrypt(). +// +// Automatically decompresses plaintext, but returns an error if the decompressed +// data would be >250kB or >3x the size of the compressed data, whichever is larger. +func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) { + globalHeaders := obj.mergedHeaders(nil) + + critical, err := globalHeaders.getCritical() + if err != nil { + return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: invalid crit header") + } + + if len(critical) > 0 { + return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: unsupported crit header") + } + + key, err := tryJWKS(decryptionKey, obj.Header) + if err != nil { + return -1, Header{}, nil, err + } + decrypter, err := newDecrypter(key) + if err != nil { + return -1, Header{}, nil, err + } + + encryption := globalHeaders.getEncryption() + cipher := getContentCipher(encryption) + if cipher == nil { + return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: unsupported enc value '%s'", string(encryption)) + } + + generator := randomKeyGenerator{ + size: cipher.keySize(), + } + + parts := &aeadParts{ + iv: obj.iv, + ciphertext: obj.ciphertext, + tag: obj.tag, + } + + authData := obj.computeAuthData() + + index := -1 + var plaintext []byte + var headers rawHeader + + for i, recipient := range obj.recipients { + recipientHeaders := obj.mergedHeaders(&recipient) + + cek, err := decrypter.decryptKey(recipientHeaders, &recipient, generator) + if err == nil { + // Found a valid CEK -- let's try to decrypt. + plaintext, err = cipher.decrypt(cek, authData, parts) + if err == nil { + index = i + headers = recipientHeaders + break + } + } + } + + if plaintext == nil { + return -1, Header{}, nil, ErrCryptoFailure + } + + // The "zip" header parameter may only be present in the protected header. + if comp := obj.protected.getCompression(); comp != "" { + plaintext, err = decompress(comp, plaintext) + if err != nil { + return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: failed to decompress plaintext: %v", err) + } + } + + sanitized, err := headers.sanitized() + if err != nil { + return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: failed to sanitize header: %v", err) + } + + return index, sanitized, plaintext, err +} diff --git a/vendor/github.com/go-jose/go-jose/v4/doc.go b/vendor/github.com/go-jose/go-jose/v4/doc.go new file mode 100644 index 00000000000..0ad40ca085f --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/doc.go @@ -0,0 +1,25 @@ +/*- + * Copyright 2014 Square Inc. + * + * 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 jose aims to provide an implementation of the Javascript Object Signing +and Encryption set of standards. It implements encryption and signing based on +the JSON Web Encryption and JSON Web Signature standards, with optional JSON Web +Token support available in a sub-package. The library supports both the compact +and JWS/JWE JSON Serialization formats, and has optional support for multiple +recipients. +*/ +package jose diff --git a/vendor/github.com/go-jose/go-jose/v4/encoding.go b/vendor/github.com/go-jose/go-jose/v4/encoding.go new file mode 100644 index 00000000000..4f6e0d4a5cf --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/encoding.go @@ -0,0 +1,228 @@ +/*- + * Copyright 2014 Square Inc. + * + * 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 jose + +import ( + "bytes" + "compress/flate" + "encoding/base64" + "encoding/binary" + "fmt" + "io" + "math/big" + "strings" + "unicode" + + "github.com/go-jose/go-jose/v4/json" +) + +// Helper function to serialize known-good objects. +// Precondition: value is not a nil pointer. +func mustSerializeJSON(value interface{}) []byte { + out, err := json.Marshal(value) + if err != nil { + panic(err) + } + // We never want to serialize the top-level value "null," since it's not a + // valid JOSE message. But if a caller passes in a nil pointer to this method, + // MarshalJSON will happily serialize it as the top-level value "null". If + // that value is then embedded in another operation, for instance by being + // base64-encoded and fed as input to a signing algorithm + // (https://github.com/go-jose/go-jose/issues/22), the result will be + // incorrect. Because this method is intended for known-good objects, and a nil + // pointer is not a known-good object, we are free to panic in this case. + // Note: It's not possible to directly check whether the data pointed at by an + // interface is a nil pointer, so we do this hacky workaround. + // https://groups.google.com/forum/#!topic/golang-nuts/wnH302gBa4I + if string(out) == "null" { + panic("Tried to serialize a nil pointer.") + } + return out +} + +// Strip all newlines and whitespace +func stripWhitespace(data string) string { + buf := strings.Builder{} + buf.Grow(len(data)) + for _, r := range data { + if !unicode.IsSpace(r) { + buf.WriteRune(r) + } + } + return buf.String() +} + +// Perform compression based on algorithm +func compress(algorithm CompressionAlgorithm, input []byte) ([]byte, error) { + switch algorithm { + case DEFLATE: + return deflate(input) + default: + return nil, ErrUnsupportedAlgorithm + } +} + +// Perform decompression based on algorithm +func decompress(algorithm CompressionAlgorithm, input []byte) ([]byte, error) { + switch algorithm { + case DEFLATE: + return inflate(input) + default: + return nil, ErrUnsupportedAlgorithm + } +} + +// deflate compresses the input. +func deflate(input []byte) ([]byte, error) { + output := new(bytes.Buffer) + + // Writing to byte buffer, err is always nil + writer, _ := flate.NewWriter(output, 1) + _, _ = io.Copy(writer, bytes.NewBuffer(input)) + + err := writer.Close() + return output.Bytes(), err +} + +// inflate decompresses the input. +// +// Errors if the decompressed data would be >250kB or >10x the size of the +// compressed data, whichever is larger. +func inflate(input []byte) ([]byte, error) { + output := new(bytes.Buffer) + reader := flate.NewReader(bytes.NewBuffer(input)) + + maxCompressedSize := max(250_000, 10*int64(len(input))) + + limit := maxCompressedSize + 1 + n, err := io.CopyN(output, reader, limit) + if err != nil && err != io.EOF { + return nil, err + } + if n == limit { + return nil, fmt.Errorf("uncompressed data would be too large (>%d bytes)", maxCompressedSize) + } + + err = reader.Close() + return output.Bytes(), err +} + +// byteBuffer represents a slice of bytes that can be serialized to url-safe base64. +type byteBuffer struct { + data []byte +} + +func newBuffer(data []byte) *byteBuffer { + if data == nil { + return nil + } + return &byteBuffer{ + data: data, + } +} + +func newFixedSizeBuffer(data []byte, length int) *byteBuffer { + if len(data) > length { + panic("go-jose/go-jose: invalid call to newFixedSizeBuffer (len(data) > length)") + } + pad := make([]byte, length-len(data)) + return newBuffer(append(pad, data...)) +} + +func newBufferFromInt(num uint64) *byteBuffer { + data := make([]byte, 8) + binary.BigEndian.PutUint64(data, num) + return newBuffer(bytes.TrimLeft(data, "\x00")) +} + +func (b *byteBuffer) MarshalJSON() ([]byte, error) { + return json.Marshal(b.base64()) +} + +func (b *byteBuffer) UnmarshalJSON(data []byte) error { + var encoded string + err := json.Unmarshal(data, &encoded) + if err != nil { + return err + } + + if encoded == "" { + return nil + } + + decoded, err := base64.RawURLEncoding.DecodeString(encoded) + if err != nil { + return err + } + + *b = *newBuffer(decoded) + + return nil +} + +func (b *byteBuffer) base64() string { + return base64.RawURLEncoding.EncodeToString(b.data) +} + +func (b *byteBuffer) bytes() []byte { + // Handling nil here allows us to transparently handle nil slices when serializing. + if b == nil { + return nil + } + return b.data +} + +func (b byteBuffer) bigInt() *big.Int { + return new(big.Int).SetBytes(b.data) +} + +func (b byteBuffer) toInt() int { + return int(b.bigInt().Int64()) +} + +func base64EncodeLen(sl []byte) int { + return base64.RawURLEncoding.EncodedLen(len(sl)) +} + +func base64JoinWithDots(inputs ...[]byte) string { + if len(inputs) == 0 { + return "" + } + + // Count of dots. + totalCount := len(inputs) - 1 + + for _, input := range inputs { + totalCount += base64EncodeLen(input) + } + + out := make([]byte, totalCount) + startEncode := 0 + for i, input := range inputs { + base64.RawURLEncoding.Encode(out[startEncode:], input) + + if i == len(inputs)-1 { + continue + } + + startEncode += base64EncodeLen(input) + out[startEncode] = '.' + startEncode++ + } + + return string(out) +} diff --git a/vendor/github.com/go-jose/go-jose/v4/json/LICENSE b/vendor/github.com/go-jose/go-jose/v4/json/LICENSE new file mode 100644 index 00000000000..74487567632 --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/json/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2012 The Go Authors. 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/go-jose/go-jose/v4/json/README.md b/vendor/github.com/go-jose/go-jose/v4/json/README.md new file mode 100644 index 00000000000..86de5e5581f --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/json/README.md @@ -0,0 +1,13 @@ +# Safe JSON + +This repository contains a fork of the `encoding/json` package from Go 1.6. + +The following changes were made: + +* Object deserialization uses case-sensitive member name matching instead of + [case-insensitive matching](https://www.ietf.org/mail-archive/web/json/current/msg03763.html). + This is to avoid differences in the interpretation of JOSE messages between + go-jose and libraries written in other languages. +* When deserializing a JSON object, we check for duplicate keys and reject the + input whenever we detect a duplicate. Rather than trying to work with malformed + data, we prefer to reject it right away. diff --git a/vendor/github.com/go-jose/go-jose/v4/json/decode.go b/vendor/github.com/go-jose/go-jose/v4/json/decode.go new file mode 100644 index 00000000000..50634dd8478 --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/json/decode.go @@ -0,0 +1,1216 @@ +// Copyright 2010 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. + +// Represents JSON data structure using native Go types: booleans, floats, +// strings, arrays, and maps. + +package json + +import ( + "bytes" + "encoding" + "encoding/base64" + "errors" + "fmt" + "math" + "reflect" + "runtime" + "strconv" + "unicode" + "unicode/utf16" + "unicode/utf8" +) + +// Unmarshal parses the JSON-encoded data and stores the result +// in the value pointed to by v. +// +// Unmarshal uses the inverse of the encodings that +// Marshal uses, allocating maps, slices, and pointers as necessary, +// with the following additional rules: +// +// To unmarshal JSON into a pointer, Unmarshal first handles the case of +// the JSON being the JSON literal null. In that case, Unmarshal sets +// the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into +// the value pointed at by the pointer. If the pointer is nil, Unmarshal +// allocates a new value for it to point to. +// +// To unmarshal JSON into a struct, Unmarshal matches incoming object +// keys to the keys used by Marshal (either the struct field name or its tag), +// preferring an exact match but also accepting a case-insensitive match. +// Unmarshal will only set exported fields of the struct. +// +// To unmarshal JSON into an interface value, +// Unmarshal stores one of these in the interface value: +// +// bool, for JSON booleans +// float64, for JSON numbers +// string, for JSON strings +// []interface{}, for JSON arrays +// map[string]interface{}, for JSON objects +// nil for JSON null +// +// To unmarshal a JSON array into a slice, Unmarshal resets the slice length +// to zero and then appends each element to the slice. +// As a special case, to unmarshal an empty JSON array into a slice, +// Unmarshal replaces the slice with a new empty slice. +// +// To unmarshal a JSON array into a Go array, Unmarshal decodes +// JSON array elements into corresponding Go array elements. +// If the Go array is smaller than the JSON array, +// the additional JSON array elements are discarded. +// If the JSON array is smaller than the Go array, +// the additional Go array elements are set to zero values. +// +// To unmarshal a JSON object into a string-keyed map, Unmarshal first +// establishes a map to use, If the map is nil, Unmarshal allocates a new map. +// Otherwise Unmarshal reuses the existing map, keeping existing entries. +// Unmarshal then stores key-value pairs from the JSON object into the map. +// +// If a JSON value is not appropriate for a given target type, +// or if a JSON number overflows the target type, Unmarshal +// skips that field and completes the unmarshaling as best it can. +// If no more serious errors are encountered, Unmarshal returns +// an UnmarshalTypeError describing the earliest such error. +// +// The JSON null value unmarshals into an interface, map, pointer, or slice +// by setting that Go value to nil. Because null is often used in JSON to mean +// “not present,” unmarshaling a JSON null into any other Go type has no effect +// on the value and produces no error. +// +// When unmarshaling quoted strings, invalid UTF-8 or +// invalid UTF-16 surrogate pairs are not treated as an error. +// Instead, they are replaced by the Unicode replacement +// character U+FFFD. +func Unmarshal(data []byte, v interface{}) error { + // Check for well-formedness. + // Avoids filling out half a data structure + // before discovering a JSON syntax error. + var d decodeState + err := checkValid(data, &d.scan) + if err != nil { + return err + } + + d.init(data) + return d.unmarshal(v) +} + +// Unmarshaler is the interface implemented by objects +// that can unmarshal a JSON description of themselves. +// The input can be assumed to be a valid encoding of +// a JSON value. UnmarshalJSON must copy the JSON data +// if it wishes to retain the data after returning. +type Unmarshaler interface { + UnmarshalJSON([]byte) error +} + +// An UnmarshalTypeError describes a JSON value that was +// not appropriate for a value of a specific Go type. +type UnmarshalTypeError struct { + Value string // description of JSON value - "bool", "array", "number -5" + Type reflect.Type // type of Go value it could not be assigned to + Offset int64 // error occurred after reading Offset bytes +} + +func (e *UnmarshalTypeError) Error() string { + return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String() +} + +// An UnmarshalFieldError describes a JSON object key that +// led to an unexported (and therefore unwritable) struct field. +// (No longer used; kept for compatibility.) +type UnmarshalFieldError struct { + Key string + Type reflect.Type + Field reflect.StructField +} + +func (e *UnmarshalFieldError) Error() string { + return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String() +} + +// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal. +// (The argument to Unmarshal must be a non-nil pointer.) +type InvalidUnmarshalError struct { + Type reflect.Type +} + +func (e *InvalidUnmarshalError) Error() string { + if e.Type == nil { + return "json: Unmarshal(nil)" + } + + if e.Type.Kind() != reflect.Ptr { + return "json: Unmarshal(non-pointer " + e.Type.String() + ")" + } + return "json: Unmarshal(nil " + e.Type.String() + ")" +} + +func (d *decodeState) unmarshal(v interface{}) (err error) { + defer func() { + if r := recover(); r != nil { + if _, ok := r.(runtime.Error); ok { + panic(r) + } + err = r.(error) + } + }() + + rv := reflect.ValueOf(v) + if rv.Kind() != reflect.Ptr || rv.IsNil() { + return &InvalidUnmarshalError{reflect.TypeOf(v)} + } + + d.scan.reset() + // We decode rv not rv.Elem because the Unmarshaler interface + // test must be applied at the top level of the value. + d.value(rv) + return d.savedError +} + +// A Number represents a JSON number literal. +type Number string + +// String returns the literal text of the number. +func (n Number) String() string { return string(n) } + +// Float64 returns the number as a float64. +func (n Number) Float64() (float64, error) { + return strconv.ParseFloat(string(n), 64) +} + +// Int64 returns the number as an int64. +func (n Number) Int64() (int64, error) { + return strconv.ParseInt(string(n), 10, 64) +} + +// isValidNumber reports whether s is a valid JSON number literal. +func isValidNumber(s string) bool { + // This function implements the JSON numbers grammar. + // See https://tools.ietf.org/html/rfc7159#section-6 + // and http://json.org/number.gif + + if s == "" { + return false + } + + // Optional - + if s[0] == '-' { + s = s[1:] + if s == "" { + return false + } + } + + // Digits + switch { + default: + return false + + case s[0] == '0': + s = s[1:] + + case '1' <= s[0] && s[0] <= '9': + s = s[1:] + for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { + s = s[1:] + } + } + + // . followed by 1 or more digits. + if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' { + s = s[2:] + for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { + s = s[1:] + } + } + + // e or E followed by an optional - or + and + // 1 or more digits. + if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') { + s = s[1:] + if s[0] == '+' || s[0] == '-' { + s = s[1:] + if s == "" { + return false + } + } + for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { + s = s[1:] + } + } + + // Make sure we are at the end. + return s == "" +} + +type NumberUnmarshalType int + +const ( + // unmarshal a JSON number into an interface{} as a float64 + UnmarshalFloat NumberUnmarshalType = iota + // unmarshal a JSON number into an interface{} as a `json.Number` + UnmarshalJSONNumber + // unmarshal a JSON number into an interface{} as a int64 + // if value is an integer otherwise float64 + UnmarshalIntOrFloat +) + +// decodeState represents the state while decoding a JSON value. +type decodeState struct { + data []byte + off int // read offset in data + scan scanner + nextscan scanner // for calls to nextValue + savedError error + numberType NumberUnmarshalType +} + +// errPhase is used for errors that should not happen unless +// there is a bug in the JSON decoder or something is editing +// the data slice while the decoder executes. +var errPhase = errors.New("JSON decoder out of sync - data changing underfoot?") + +func (d *decodeState) init(data []byte) *decodeState { + d.data = data + d.off = 0 + d.savedError = nil + return d +} + +// error aborts the decoding by panicking with err. +func (d *decodeState) error(err error) { + panic(err) +} + +// saveError saves the first err it is called with, +// for reporting at the end of the unmarshal. +func (d *decodeState) saveError(err error) { + if d.savedError == nil { + d.savedError = err + } +} + +// next cuts off and returns the next full JSON value in d.data[d.off:]. +// The next value is known to be an object or array, not a literal. +func (d *decodeState) next() []byte { + c := d.data[d.off] + item, rest, err := nextValue(d.data[d.off:], &d.nextscan) + if err != nil { + d.error(err) + } + d.off = len(d.data) - len(rest) + + // Our scanner has seen the opening brace/bracket + // and thinks we're still in the middle of the object. + // invent a closing brace/bracket to get it out. + if c == '{' { + d.scan.step(&d.scan, '}') + } else { + d.scan.step(&d.scan, ']') + } + + return item +} + +// scanWhile processes bytes in d.data[d.off:] until it +// receives a scan code not equal to op. +// It updates d.off and returns the new scan code. +func (d *decodeState) scanWhile(op int) int { + var newOp int + for { + if d.off >= len(d.data) { + newOp = d.scan.eof() + d.off = len(d.data) + 1 // mark processed EOF with len+1 + } else { + c := d.data[d.off] + d.off++ + newOp = d.scan.step(&d.scan, c) + } + if newOp != op { + break + } + } + return newOp +} + +// value decodes a JSON value from d.data[d.off:] into the value. +// it updates d.off to point past the decoded value. +func (d *decodeState) value(v reflect.Value) { + if !v.IsValid() { + _, rest, err := nextValue(d.data[d.off:], &d.nextscan) + if err != nil { + d.error(err) + } + d.off = len(d.data) - len(rest) + + // d.scan thinks we're still at the beginning of the item. + // Feed in an empty string - the shortest, simplest value - + // so that it knows we got to the end of the value. + if d.scan.redo { + // rewind. + d.scan.redo = false + d.scan.step = stateBeginValue + } + d.scan.step(&d.scan, '"') + d.scan.step(&d.scan, '"') + + n := len(d.scan.parseState) + if n > 0 && d.scan.parseState[n-1] == parseObjectKey { + // d.scan thinks we just read an object key; finish the object + d.scan.step(&d.scan, ':') + d.scan.step(&d.scan, '"') + d.scan.step(&d.scan, '"') + d.scan.step(&d.scan, '}') + } + + return + } + + switch op := d.scanWhile(scanSkipSpace); op { + default: + d.error(errPhase) + + case scanBeginArray: + d.array(v) + + case scanBeginObject: + d.object(v) + + case scanBeginLiteral: + d.literal(v) + } +} + +type unquotedValue struct{} + +// valueQuoted is like value but decodes a +// quoted string literal or literal null into an interface value. +// If it finds anything other than a quoted string literal or null, +// valueQuoted returns unquotedValue{}. +func (d *decodeState) valueQuoted() interface{} { + switch op := d.scanWhile(scanSkipSpace); op { + default: + d.error(errPhase) + + case scanBeginArray: + d.array(reflect.Value{}) + + case scanBeginObject: + d.object(reflect.Value{}) + + case scanBeginLiteral: + switch v := d.literalInterface().(type) { + case nil, string: + return v + } + } + return unquotedValue{} +} + +// indirect walks down v allocating pointers as needed, +// until it gets to a non-pointer. +// if it encounters an Unmarshaler, indirect stops and returns that. +// if decodingNull is true, indirect stops at the last pointer so it can be set to nil. +func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) { + // If v is a named type and is addressable, + // start with its address, so that if the type has pointer methods, + // we find them. + if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() { + v = v.Addr() + } + for { + // Load value from interface, but only if the result will be + // usefully addressable. + if v.Kind() == reflect.Interface && !v.IsNil() { + e := v.Elem() + if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) { + v = e + continue + } + } + + if v.Kind() != reflect.Ptr { + break + } + + if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() { + break + } + if v.IsNil() { + v.Set(reflect.New(v.Type().Elem())) + } + if v.Type().NumMethod() > 0 { + if u, ok := v.Interface().(Unmarshaler); ok { + return u, nil, reflect.Value{} + } + if u, ok := v.Interface().(encoding.TextUnmarshaler); ok { + return nil, u, reflect.Value{} + } + } + v = v.Elem() + } + return nil, nil, v +} + +// array consumes an array from d.data[d.off-1:], decoding into the value v. +// the first byte of the array ('[') has been read already. +func (d *decodeState) array(v reflect.Value) { + // Check for unmarshaler. + u, ut, pv := d.indirect(v, false) + if u != nil { + d.off-- + err := u.UnmarshalJSON(d.next()) + if err != nil { + d.error(err) + } + return + } + if ut != nil { + d.saveError(&UnmarshalTypeError{"array", v.Type(), int64(d.off)}) + d.off-- + d.next() + return + } + + v = pv + + // Check type of target. + switch v.Kind() { + case reflect.Interface: + if v.NumMethod() == 0 { + // Decoding into nil interface? Switch to non-reflect code. + v.Set(reflect.ValueOf(d.arrayInterface())) + return + } + // Otherwise it's invalid. + fallthrough + default: + d.saveError(&UnmarshalTypeError{"array", v.Type(), int64(d.off)}) + d.off-- + d.next() + return + case reflect.Array: + case reflect.Slice: + break + } + + i := 0 + for { + // Look ahead for ] - can only happen on first iteration. + op := d.scanWhile(scanSkipSpace) + if op == scanEndArray { + break + } + + // Back up so d.value can have the byte we just read. + d.off-- + d.scan.undo(op) + + // Get element of array, growing if necessary. + if v.Kind() == reflect.Slice { + // Grow slice if necessary + if i >= v.Cap() { + newcap := v.Cap() + v.Cap()/2 + if newcap < 4 { + newcap = 4 + } + newv := reflect.MakeSlice(v.Type(), v.Len(), newcap) + reflect.Copy(newv, v) + v.Set(newv) + } + if i >= v.Len() { + v.SetLen(i + 1) + } + } + + if i < v.Len() { + // Decode into element. + d.value(v.Index(i)) + } else { + // Ran out of fixed array: skip. + d.value(reflect.Value{}) + } + i++ + + // Next token must be , or ]. + op = d.scanWhile(scanSkipSpace) + if op == scanEndArray { + break + } + if op != scanArrayValue { + d.error(errPhase) + } + } + + if i < v.Len() { + if v.Kind() == reflect.Array { + // Array. Zero the rest. + z := reflect.Zero(v.Type().Elem()) + for ; i < v.Len(); i++ { + v.Index(i).Set(z) + } + } else { + v.SetLen(i) + } + } + if i == 0 && v.Kind() == reflect.Slice { + v.Set(reflect.MakeSlice(v.Type(), 0, 0)) + } +} + +var nullLiteral = []byte("null") + +// object consumes an object from d.data[d.off-1:], decoding into the value v. +// the first byte ('{') of the object has been read already. +func (d *decodeState) object(v reflect.Value) { + // Check for unmarshaler. + u, ut, pv := d.indirect(v, false) + if u != nil { + d.off-- + err := u.UnmarshalJSON(d.next()) + if err != nil { + d.error(err) + } + return + } + if ut != nil { + d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)}) + d.off-- + d.next() // skip over { } in input + return + } + v = pv + + // Decoding into nil interface? Switch to non-reflect code. + if v.Kind() == reflect.Interface && v.NumMethod() == 0 { + v.Set(reflect.ValueOf(d.objectInterface())) + return + } + + // Check type of target: struct or map[string]T + switch v.Kind() { + case reflect.Map: + // map must have string kind + t := v.Type() + if t.Key().Kind() != reflect.String { + d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)}) + d.off-- + d.next() // skip over { } in input + return + } + if v.IsNil() { + v.Set(reflect.MakeMap(t)) + } + case reflect.Struct: + + default: + d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)}) + d.off-- + d.next() // skip over { } in input + return + } + + var mapElem reflect.Value + keys := map[string]bool{} + + for { + // Read opening " of string key or closing }. + op := d.scanWhile(scanSkipSpace) + if op == scanEndObject { + // closing } - can only happen on first iteration. + break + } + if op != scanBeginLiteral { + d.error(errPhase) + } + + // Read key. + start := d.off - 1 + op = d.scanWhile(scanContinue) + item := d.data[start : d.off-1] + key, ok := unquote(item) + if !ok { + d.error(errPhase) + } + + // Check for duplicate keys. + _, ok = keys[key] + if !ok { + keys[key] = true + } else { + d.error(fmt.Errorf("json: duplicate key '%s' in object", key)) + } + + // Figure out field corresponding to key. + var subv reflect.Value + destring := false // whether the value is wrapped in a string to be decoded first + + if v.Kind() == reflect.Map { + elemType := v.Type().Elem() + if !mapElem.IsValid() { + mapElem = reflect.New(elemType).Elem() + } else { + mapElem.Set(reflect.Zero(elemType)) + } + subv = mapElem + } else { + var f *field + fields := cachedTypeFields(v.Type()) + for i := range fields { + ff := &fields[i] + if bytes.Equal(ff.nameBytes, []byte(key)) { + f = ff + break + } + } + if f != nil { + subv = v + destring = f.quoted + for _, i := range f.index { + if subv.Kind() == reflect.Ptr { + if subv.IsNil() { + subv.Set(reflect.New(subv.Type().Elem())) + } + subv = subv.Elem() + } + subv = subv.Field(i) + } + } + } + + // Read : before value. + if op == scanSkipSpace { + op = d.scanWhile(scanSkipSpace) + } + if op != scanObjectKey { + d.error(errPhase) + } + + // Read value. + if destring { + switch qv := d.valueQuoted().(type) { + case nil: + d.literalStore(nullLiteral, subv, false) + case string: + d.literalStore([]byte(qv), subv, true) + default: + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", subv.Type())) + } + } else { + d.value(subv) + } + + // Write value back to map; + // if using struct, subv points into struct already. + if v.Kind() == reflect.Map { + kv := reflect.ValueOf(key).Convert(v.Type().Key()) + v.SetMapIndex(kv, subv) + } + + // Next token must be , or }. + op = d.scanWhile(scanSkipSpace) + if op == scanEndObject { + break + } + if op != scanObjectValue { + d.error(errPhase) + } + } +} + +// literal consumes a literal from d.data[d.off-1:], decoding into the value v. +// The first byte of the literal has been read already +// (that's how the caller knows it's a literal). +func (d *decodeState) literal(v reflect.Value) { + // All bytes inside literal return scanContinue op code. + start := d.off - 1 + op := d.scanWhile(scanContinue) + + // Scan read one byte too far; back up. + d.off-- + d.scan.undo(op) + + d.literalStore(d.data[start:d.off], v, false) +} + +// convertNumber converts the number literal s to a float64, int64 or a Number +// depending on d.numberDecodeType. +func (d *decodeState) convertNumber(s string) (interface{}, error) { + switch d.numberType { + + case UnmarshalJSONNumber: + return Number(s), nil + case UnmarshalIntOrFloat: + v, err := strconv.ParseInt(s, 10, 64) + if err == nil { + return v, nil + } + + // tries to parse integer number in scientific notation + f, err := strconv.ParseFloat(s, 64) + if err != nil { + return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0), int64(d.off)} + } + + // if it has no decimal value use int64 + if fi, fd := math.Modf(f); fd == 0.0 { + return int64(fi), nil + } + return f, nil + default: + f, err := strconv.ParseFloat(s, 64) + if err != nil { + return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0), int64(d.off)} + } + return f, nil + } + +} + +var numberType = reflect.TypeOf(Number("")) + +// literalStore decodes a literal stored in item into v. +// +// fromQuoted indicates whether this literal came from unwrapping a +// string from the ",string" struct tag option. this is used only to +// produce more helpful error messages. +func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) { + // Check for unmarshaler. + if len(item) == 0 { + //Empty string given + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + return + } + wantptr := item[0] == 'n' // null + u, ut, pv := d.indirect(v, wantptr) + if u != nil { + err := u.UnmarshalJSON(item) + if err != nil { + d.error(err) + } + return + } + if ut != nil { + if item[0] != '"' { + if fromQuoted { + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + } else { + d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)}) + } + return + } + s, ok := unquoteBytes(item) + if !ok { + if fromQuoted { + d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + } else { + d.error(errPhase) + } + } + err := ut.UnmarshalText(s) + if err != nil { + d.error(err) + } + return + } + + v = pv + + switch c := item[0]; c { + case 'n': // null + switch v.Kind() { + case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: + v.Set(reflect.Zero(v.Type())) + // otherwise, ignore null for primitives/string + } + case 't', 'f': // true, false + value := c == 't' + switch v.Kind() { + default: + if fromQuoted { + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + } else { + d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)}) + } + case reflect.Bool: + v.SetBool(value) + case reflect.Interface: + if v.NumMethod() == 0 { + v.Set(reflect.ValueOf(value)) + } else { + d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)}) + } + } + + case '"': // string + s, ok := unquoteBytes(item) + if !ok { + if fromQuoted { + d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + } else { + d.error(errPhase) + } + } + switch v.Kind() { + default: + d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)}) + case reflect.Slice: + if v.Type().Elem().Kind() != reflect.Uint8 { + d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)}) + break + } + b := make([]byte, base64.StdEncoding.DecodedLen(len(s))) + n, err := base64.StdEncoding.Decode(b, s) + if err != nil { + d.saveError(err) + break + } + v.SetBytes(b[:n]) + case reflect.String: + v.SetString(string(s)) + case reflect.Interface: + if v.NumMethod() == 0 { + v.Set(reflect.ValueOf(string(s))) + } else { + d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)}) + } + } + + default: // number + if c != '-' && (c < '0' || c > '9') { + if fromQuoted { + d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + } else { + d.error(errPhase) + } + } + s := string(item) + switch v.Kind() { + default: + if v.Kind() == reflect.String && v.Type() == numberType { + v.SetString(s) + if !isValidNumber(s) { + d.error(fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item)) + } + break + } + if fromQuoted { + d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + } else { + d.error(&UnmarshalTypeError{"number", v.Type(), int64(d.off)}) + } + case reflect.Interface: + n, err := d.convertNumber(s) + if err != nil { + d.saveError(err) + break + } + if v.NumMethod() != 0 { + d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)}) + break + } + v.Set(reflect.ValueOf(n)) + + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + n, err := strconv.ParseInt(s, 10, 64) + if err != nil || v.OverflowInt(n) { + d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)}) + break + } + v.SetInt(n) + + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + n, err := strconv.ParseUint(s, 10, 64) + if err != nil || v.OverflowUint(n) { + d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)}) + break + } + v.SetUint(n) + + case reflect.Float32, reflect.Float64: + n, err := strconv.ParseFloat(s, v.Type().Bits()) + if err != nil || v.OverflowFloat(n) { + d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)}) + break + } + v.SetFloat(n) + } + } +} + +// The xxxInterface routines build up a value to be stored +// in an empty interface. They are not strictly necessary, +// but they avoid the weight of reflection in this common case. + +// valueInterface is like value but returns interface{} +func (d *decodeState) valueInterface() interface{} { + switch d.scanWhile(scanSkipSpace) { + default: + d.error(errPhase) + panic("unreachable") + case scanBeginArray: + return d.arrayInterface() + case scanBeginObject: + return d.objectInterface() + case scanBeginLiteral: + return d.literalInterface() + } +} + +// arrayInterface is like array but returns []interface{}. +func (d *decodeState) arrayInterface() []interface{} { + var v = make([]interface{}, 0) + for { + // Look ahead for ] - can only happen on first iteration. + op := d.scanWhile(scanSkipSpace) + if op == scanEndArray { + break + } + + // Back up so d.value can have the byte we just read. + d.off-- + d.scan.undo(op) + + v = append(v, d.valueInterface()) + + // Next token must be , or ]. + op = d.scanWhile(scanSkipSpace) + if op == scanEndArray { + break + } + if op != scanArrayValue { + d.error(errPhase) + } + } + return v +} + +// objectInterface is like object but returns map[string]interface{}. +func (d *decodeState) objectInterface() map[string]interface{} { + m := make(map[string]interface{}) + keys := map[string]bool{} + + for { + // Read opening " of string key or closing }. + op := d.scanWhile(scanSkipSpace) + if op == scanEndObject { + // closing } - can only happen on first iteration. + break + } + if op != scanBeginLiteral { + d.error(errPhase) + } + + // Read string key. + start := d.off - 1 + op = d.scanWhile(scanContinue) + item := d.data[start : d.off-1] + key, ok := unquote(item) + if !ok { + d.error(errPhase) + } + + // Check for duplicate keys. + _, ok = keys[key] + if !ok { + keys[key] = true + } else { + d.error(fmt.Errorf("json: duplicate key '%s' in object", key)) + } + + // Read : before value. + if op == scanSkipSpace { + op = d.scanWhile(scanSkipSpace) + } + if op != scanObjectKey { + d.error(errPhase) + } + + // Read value. + m[key] = d.valueInterface() + + // Next token must be , or }. + op = d.scanWhile(scanSkipSpace) + if op == scanEndObject { + break + } + if op != scanObjectValue { + d.error(errPhase) + } + } + return m +} + +// literalInterface is like literal but returns an interface value. +func (d *decodeState) literalInterface() interface{} { + // All bytes inside literal return scanContinue op code. + start := d.off - 1 + op := d.scanWhile(scanContinue) + + // Scan read one byte too far; back up. + d.off-- + d.scan.undo(op) + item := d.data[start:d.off] + + switch c := item[0]; c { + case 'n': // null + return nil + + case 't', 'f': // true, false + return c == 't' + + case '"': // string + s, ok := unquote(item) + if !ok { + d.error(errPhase) + } + return s + + default: // number + if c != '-' && (c < '0' || c > '9') { + d.error(errPhase) + } + n, err := d.convertNumber(string(item)) + if err != nil { + d.saveError(err) + } + return n + } +} + +// getu4 decodes \uXXXX from the beginning of s, returning the hex value, +// or it returns -1. +func getu4(s []byte) rune { + if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { + return -1 + } + r, err := strconv.ParseUint(string(s[2:6]), 16, 64) + if err != nil { + return -1 + } + return rune(r) +} + +// unquote converts a quoted JSON string literal s into an actual string t. +// The rules are different than for Go, so cannot use strconv.Unquote. +func unquote(s []byte) (t string, ok bool) { + s, ok = unquoteBytes(s) + t = string(s) + return +} + +func unquoteBytes(s []byte) (t []byte, ok bool) { + if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { + return + } + s = s[1 : len(s)-1] + + // Check for unusual characters. If there are none, + // then no unquoting is needed, so return a slice of the + // original bytes. + r := 0 + for r < len(s) { + c := s[r] + if c == '\\' || c == '"' || c < ' ' { + break + } + if c < utf8.RuneSelf { + r++ + continue + } + rr, size := utf8.DecodeRune(s[r:]) + if rr == utf8.RuneError && size == 1 { + break + } + r += size + } + if r == len(s) { + return s, true + } + + b := make([]byte, len(s)+2*utf8.UTFMax) + w := copy(b, s[0:r]) + for r < len(s) { + // Out of room? Can only happen if s is full of + // malformed UTF-8 and we're replacing each + // byte with RuneError. + if w >= len(b)-2*utf8.UTFMax { + nb := make([]byte, (len(b)+utf8.UTFMax)*2) + copy(nb, b[0:w]) + b = nb + } + switch c := s[r]; { + case c == '\\': + r++ + if r >= len(s) { + return + } + switch s[r] { + default: + return + case '"', '\\', '/', '\'': + b[w] = s[r] + r++ + w++ + case 'b': + b[w] = '\b' + r++ + w++ + case 'f': + b[w] = '\f' + r++ + w++ + case 'n': + b[w] = '\n' + r++ + w++ + case 'r': + b[w] = '\r' + r++ + w++ + case 't': + b[w] = '\t' + r++ + w++ + case 'u': + r-- + rr := getu4(s[r:]) + if rr < 0 { + return + } + r += 6 + if utf16.IsSurrogate(rr) { + rr1 := getu4(s[r:]) + if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar { + // A valid pair; consume. + r += 6 + w += utf8.EncodeRune(b[w:], dec) + break + } + // Invalid surrogate; fall back to replacement rune. + rr = unicode.ReplacementChar + } + w += utf8.EncodeRune(b[w:], rr) + } + + // Quote, control characters are invalid. + case c == '"', c < ' ': + return + + // ASCII + case c < utf8.RuneSelf: + b[w] = c + r++ + w++ + + // Coerce to well-formed UTF-8. + default: + rr, size := utf8.DecodeRune(s[r:]) + r += size + w += utf8.EncodeRune(b[w:], rr) + } + } + return b[0:w], true +} diff --git a/vendor/github.com/go-jose/go-jose/v4/json/encode.go b/vendor/github.com/go-jose/go-jose/v4/json/encode.go new file mode 100644 index 00000000000..98de68ce1e9 --- /dev/null +++ b/vendor/github.com/go-jose/go-jose/v4/json/encode.go @@ -0,0 +1,1197 @@ +// Copyright 2010 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 json implements encoding and decoding of JSON objects as defined in +// RFC 4627. The mapping between JSON objects and Go values is described +// in the documentation for the Marshal and Unmarshal functions. +// +// See "JSON and Go" for an introduction to this package: +// https://golang.org/doc/articles/json_and_go.html +package json + +import ( + "bytes" + "encoding" + "encoding/base64" + "fmt" + "math" + "reflect" + "runtime" + "sort" + "strconv" + "strings" + "sync" + "unicode" + "unicode/utf8" +) + +// Marshal returns the JSON encoding of v. +// +// Marshal traverses the value v recursively. +// If an encountered value implements the Marshaler interface +// and is not a nil pointer, Marshal calls its MarshalJSON method +// to produce JSON. If no MarshalJSON method is present but the +// value implements encoding.TextMarshaler instead, Marshal calls +// its MarshalText method. +// The nil pointer exception is not strictly necessary +// but mimics a similar, necessary exception in the behavior of +// UnmarshalJSON. +// +// Otherwise, Marshal uses the following type-dependent default encodings: +// +// Boolean values encode as JSON booleans. +// +// Floating point, integer, and Number values encode as JSON numbers. +// +// String values encode as JSON strings coerced to valid UTF-8, +// replacing invalid bytes with the Unicode replacement rune. +// The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e" +// to keep some browsers from misinterpreting JSON output as HTML. +// Ampersand "&" is also escaped to "\u0026" for the same reason. +// +// Array and slice values encode as JSON arrays, except that +// []byte encodes as a base64-encoded string, and a nil slice +// encodes as the null JSON object. +// +// Struct values encode as JSON objects. Each exported struct field +// becomes a member of the object unless +// - the field's tag is "-", or +// - the field is empty and its tag specifies the "omitempty" option. +// +// The empty values are false, 0, any +// nil pointer or interface value, and any array, slice, map, or string of +// length zero. The object's default key string is the struct field name +// but can be specified in the struct field's tag value. The "json" key in +// the struct field's tag value is the key name, followed by an optional comma +// and options. Examples: +// +// // Field is ignored by this package. +// Field int `json:"-"` +// +// // Field appears in JSON as key "myName". +// Field int `json:"myName"` +// +// // Field appears in JSON as key "myName" and +// // the field is omitted from the object if its value is empty, +// // as defined above. +// Field int `json:"myName,omitempty"` +// +// // Field appears in JSON as key "Field" (the default), but +// // the field is skipped if empty. +// // Note the leading comma. +// Field int `json:",omitempty"` +// +// The "string" option signals that a field is stored as JSON inside a +// JSON-encoded string. It applies only to fields of string, floating point, +// integer, or boolean types. This extra level of encoding is sometimes used +// when communicating with JavaScript programs: +// +// Int64String int64 `json:",string"` +// +// The key name will be used if it's a non-empty string consisting of +// only Unicode letters, digits, dollar signs, percent signs, hyphens, +// underscores and slashes. +// +// Anonymous struct fields are usually marshaled as if their inner exported fields +// were fields in the outer struct, subject to the usual Go visibility rules amended +// as described in the next paragraph. +// An anonymous struct field with a name given in its JSON tag is treated as +// having that name, rather than being anonymous. +// An anonymous struct field of interface type is treated the same as having +// that type as its name, rather than being anonymous. +// +// The Go visibility rules for struct fields are amended for JSON when +// deciding which field to marshal or unmarshal. If there are +// multiple fields at the same level, and that level is the least +// nested (and would therefore be the nesting level selected by the +// usual Go rules), the following extra rules apply: +// +// 1) Of those fields, if any are JSON-tagged, only tagged fields are considered, +// even if there are multiple untagged fields that would otherwise conflict. +// 2) If there is exactly one field (tagged or not according to the first rule), that is selected. +// 3) Otherwise there are multiple fields, and all are ignored; no error occurs. +// +// Handling of anonymous struct fields is new in Go 1.1. +// Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of +// an anonymous struct field in both current and earlier versions, give the field +// a JSON tag of "-". +// +// Map values encode as JSON objects. +// The map's key type must be string; the map keys are used as JSON object +// keys, subject to the UTF-8 coercion described for string values above. +// +// Pointer values encode as the value pointed to. +// A nil pointer encodes as the null JSON object. +// +// Interface values encode as the value contained in the interface. +// A nil interface value encodes as the null JSON object. +// +// Channel, complex, and function values cannot be encoded in JSON. +// Attempting to encode such a value causes Marshal to return +// an UnsupportedTypeError. +// +// JSON cannot represent cyclic data structures and Marshal does not +// handle them. Passing cyclic structures to Marshal will result in +// an infinite recursion. +func Marshal(v interface{}) ([]byte, error) { + e := &encodeState{} + err := e.marshal(v) + if err != nil { + return nil, err + } + return e.Bytes(), nil +} + +// MarshalIndent is like Marshal but applies Indent to format the output. +func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { + b, err := Marshal(v) + if err != nil { + return nil, err + } + var buf bytes.Buffer + err = Indent(&buf, b, prefix, indent) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029 +// characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029 +// so that the JSON will be safe to embed inside HTML