فهرست منبع

Merge branch 'emqx' of yongxu/sparrow into v2

lijian 1 سال پیش
والد
کامیت
3aaf293f3b
100فایلهای تغییر یافته به همراه9635 افزوده شده و 5177 حذف شده
  1. BIN
      .DS_Store
  2. 157 0
      go.mod
  3. 668 0
      go.sum
  4. 1 1
      install.sh
  5. 3 4
      pkg/mqtt/connection.go
  6. 13 2
      pkg/online/online.go
  7. 9 0
      pkg/protocol/emqx_device.go
  8. 128 0
      pkg/protocol/topic.go
  9. 7 6
      pkg/rpcs/common.go
  10. 4 5
      pkg/ruleEngine/nodes/mqtt_broker_node.go
  11. 1 1
      pkg/server/config.go
  12. 1 1
      pkg/server/log.go
  13. 1 2
      pkg/server/server.go
  14. 2 3
      pkg/server/server_manager.go
  15. 9 9
      pkg/tlv/tlv_test.go
  16. 2 2
      pkg/token/token.go
  17. 1 1
      pkg/utils/util.go
  18. BIN
      services/.DS_Store
  19. 37 0
      services/apiprovider/actions.go
  20. 6 0
      services/apiprovider/router.go
  21. 9 0
      services/controller/controller.go
  22. 8 1
      services/devicemanager/manager.go
  23. 260 0
      services/emqx-agent/agent.go
  24. 9 0
      services/emqx-agent/client/config.go
  25. 99 0
      services/emqx-agent/client/mqtt_client.go
  26. 6 0
      services/emqx-agent/config.toml
  27. 264 0
      services/emqx-agent/main.go
  28. 3455 0
      services/emqx-agent/protobuf/exhook.pb.go
  29. 499 0
      services/emqx-agent/protobuf/exhook.proto
  30. 868 0
      services/emqx-agent/protobuf/exhook_grpc.pb.go
  31. 10 0
      services/emqx-agent/readme.md
  32. 204 0
      services/emqx-agent/sub_dev.go
  33. 82 10
      services/httpaccess/actions.go
  34. 2 0
      services/httpaccess/router.go
  35. 1 1
      services/mqttaccess/mqtt_provider.go
  36. 9 9
      tests/device/device.go
  37. BIN
      vendor/.DS_Store
  38. 0 69
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/CONTRIBUTING.md
  39. 0 15
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/DISTRIBUTION
  40. 0 87
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/LICENSE
  41. 0 62
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/README.md
  42. 0 41
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/about.html
  43. 0 521
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/client.go
  44. 0 31
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/components.go
  45. 0 70
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/epl-v10
  46. 0 258
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/filestore.go
  47. 0 119
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/memstore.go
  48. 0 104
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/message.go
  49. 0 61
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/messageids.go
  50. 0 275
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/net.go
  51. 0 108
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/notice.html
  52. 0 27
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/oops.go
  53. 0 270
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/options.go
  54. 0 57
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/connack.go
  55. 0 128
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/connect.go
  56. 0 44
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/disconnect.go
  57. 0 324
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/packets.go
  58. 0 44
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/pingreq.go
  59. 0 44
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/pingresp.go
  60. 0 50
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/puback.go
  61. 0 50
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/pubcomp.go
  62. 0 82
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/publish.go
  63. 0 50
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/pubrec.go
  64. 0 50
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/pubrel.go
  65. 0 58
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/suback.go
  66. 0 68
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/subscribe.go
  67. 0 50
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/unsuback.go
  68. 0 61
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/unsubscribe.go
  69. 0 73
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/ping.go
  70. 0 162
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/router.go
  71. 0 125
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/store.go
  72. 0 156
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/token.go
  73. 0 82
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/topic.go
  74. 0 36
      vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/trace.go
  75. BIN
      vendor/github.com/.DS_Store
  76. 2 0
      vendor/github.com/BurntSushi/toml/.gitignore
  77. 0 3
      vendor/github.com/BurntSushi/toml/COMPATIBLE
  78. 21 14
      vendor/github.com/BurntSushi/toml/COPYING
  79. 0 19
      vendor/github.com/BurntSushi/toml/Makefile
  80. 120 0
      vendor/github.com/BurntSushi/toml/README.md
  81. 299 206
      vendor/github.com/BurntSushi/toml/decode.go
  82. 19 0
      vendor/github.com/BurntSushi/toml/decode_go116.go
  83. 0 121
      vendor/github.com/BurntSushi/toml/decode_meta.go
  84. 29 0
      vendor/github.com/BurntSushi/toml/deprecated.go
  85. 10 26
      vendor/github.com/BurntSushi/toml/doc.go
  86. 406 215
      vendor/github.com/BurntSushi/toml/encode.go
  87. 0 19
      vendor/github.com/BurntSushi/toml/encoding_types.go
  88. 0 18
      vendor/github.com/BurntSushi/toml/encoding_types_1.1.go
  89. 279 0
      vendor/github.com/BurntSushi/toml/error.go
  90. 36 0
      vendor/github.com/BurntSushi/toml/internal/tz.go
  91. 527 224
      vendor/github.com/BurntSushi/toml/lex.go
  92. 121 0
      vendor/github.com/BurntSushi/toml/meta.go
  93. 467 248
      vendor/github.com/BurntSushi/toml/parse.go
  94. 0 1
      vendor/github.com/BurntSushi/toml/session.vim
  95. 0 91
      vendor/github.com/BurntSushi/toml/type_check.go
  96. 2 2
      vendor/github.com/BurntSushi/toml/type_fields.go
  97. 70 0
      vendor/github.com/BurntSushi/toml/type_toml.go
  98. 21 0
      vendor/github.com/CloudyKit/fastprinter/LICENSE
  99. 2 0
      vendor/github.com/CloudyKit/fastprinter/README.md
  100. 369 0
      vendor/github.com/CloudyKit/fastprinter/decimal.go

BIN
.DS_Store


+ 157 - 0
go.mod

@@ -0,0 +1,157 @@
+module sparrow
+
+go 1.21.4
+
+require (
+	github.com/dgrijalva/jwt-go v3.2.0+incompatible
+	github.com/eclipse/paho.mqtt.golang v1.4.3
+	github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab
+	github.com/go-sql-driver/mysql v1.7.1
+	github.com/gogf/gf v1.16.9
+	github.com/influxdata/influxdb-client-go/v2 v2.13.0
+	github.com/iris-contrib/middleware/cors v0.0.0-20231105204038-60b21ca77167
+	github.com/iris-contrib/middleware/jwt v0.0.0-20231105204038-60b21ca77167
+	github.com/jinzhu/gorm v1.9.16
+	github.com/kataras/iris v0.0.2
+	github.com/martini-contrib/binding v0.0.0-20160701174519-05d3e151b6cf
+	github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11
+	github.com/opentracing/opentracing-go v1.2.0
+	github.com/prometheus/client_golang v1.18.0
+	github.com/robertkrimen/otto v0.3.0
+	github.com/robfig/cron v1.2.0
+	github.com/satori/go.uuid v1.2.0
+	github.com/segmentio/kafka-go v0.4.47
+	github.com/sirupsen/logrus v1.9.3
+	github.com/streadway/amqp v1.1.0
+	github.com/stretchr/testify v1.8.4
+	github.com/uber/jaeger-client-go v2.30.0+incompatible
+	go.etcd.io/etcd/client/v3 v3.5.11
+	golang.org/x/net v0.19.0
+	golang.org/x/time v0.5.0
+	google.golang.org/grpc v1.60.1
+	google.golang.org/protobuf v1.32.0
+	labix.org/v2/mgo v0.0.0-20140701140051-000000000287
+)
+
+require (
+	github.com/BurntSushi/toml v1.3.2 // indirect
+	github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect
+	github.com/CloudyKit/jet/v4 v4.1.0 // indirect
+	github.com/CloudyKit/jet/v6 v6.2.0 // indirect
+	github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect
+	github.com/Joker/jade v1.1.3 // indirect
+	github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect
+	github.com/ajg/form v1.5.1 // indirect
+	github.com/andybalholm/brotli v1.0.6 // indirect
+	github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
+	github.com/aymerick/douceur v0.2.0 // indirect
+	github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible // indirect
+	github.com/beorn7/perks v1.0.1 // indirect
+	github.com/cespare/xxhash/v2 v2.2.0 // indirect
+	github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28 // indirect
+	github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
+	github.com/coreos/go-semver v0.3.0 // indirect
+	github.com/coreos/go-systemd/v22 v22.3.2 // indirect
+	github.com/davecgh/go-spew v1.1.1 // indirect
+	github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 // indirect
+	github.com/fatih/color v1.15.0 // indirect
+	github.com/fatih/structs v1.1.0 // indirect
+	github.com/flosch/pongo2/v4 v4.0.2 // indirect
+	github.com/fsnotify/fsnotify v1.7.0 // indirect
+	github.com/gobwas/glob v0.2.3 // indirect
+	github.com/gobwas/httphead v0.1.0 // indirect
+	github.com/gobwas/pool v0.2.1 // indirect
+	github.com/gobwas/ws v1.3.0 // indirect
+	github.com/gogo/protobuf v1.3.2 // indirect
+	github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
+	github.com/golang/protobuf v1.5.3 // indirect
+	github.com/golang/snappy v0.0.4 // indirect
+	github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386 // indirect
+	github.com/gomodule/redigo v1.8.5 // indirect
+	github.com/google/go-querystring v1.1.0 // indirect
+	github.com/google/uuid v1.4.0 // indirect
+	github.com/gorilla/css v1.0.0 // indirect
+	github.com/gorilla/websocket v1.5.0 // indirect
+	github.com/grokify/html-strip-tags-go v0.0.1 // indirect
+	github.com/hashicorp/go-version v1.2.1 // indirect
+	github.com/imkira/go-interpol v1.1.0 // indirect
+	github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect
+	github.com/iris-contrib/go.uuid v2.0.0+incompatible // indirect
+	github.com/iris-contrib/httpexpect/v2 v2.15.2 // indirect
+	github.com/iris-contrib/jade v1.1.4 // indirect
+	github.com/iris-contrib/pongo2 v0.0.1 // indirect
+	github.com/iris-contrib/schema v0.0.6 // indirect
+	github.com/jinzhu/inflection v1.0.0 // indirect
+	github.com/josharian/intern v1.0.0 // indirect
+	github.com/json-iterator/go v1.1.12 // indirect
+	github.com/kataras/blocks v0.0.8 // indirect
+	github.com/kataras/golog v0.1.11 // indirect
+	github.com/kataras/iris/v12 v12.2.8 // indirect
+	github.com/kataras/neffos v0.0.22 // indirect
+	github.com/kataras/pio v0.0.13 // indirect
+	github.com/kataras/sitemap v0.0.6 // indirect
+	github.com/kataras/tunnel v0.0.4 // indirect
+	github.com/klauspost/compress v1.17.2 // indirect
+	github.com/mailgun/raymond/v2 v2.0.48 // indirect
+	github.com/mailru/easyjson v0.7.7 // indirect
+	github.com/mattn/go-colorable v0.1.13 // indirect
+	github.com/mattn/go-isatty v0.0.19 // indirect
+	github.com/mattn/go-runewidth v0.0.9 // indirect
+	github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
+	github.com/mediocregopher/radix/v3 v3.8.1 // indirect
+	github.com/microcosm-cc/bluemonday v1.0.26 // indirect
+	github.com/mitchellh/go-wordwrap v1.0.1 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/nats-io/nats.go v1.28.0 // indirect
+	github.com/nats-io/nkeys v0.4.6 // indirect
+	github.com/nats-io/nuid v1.0.1 // indirect
+	github.com/oapi-codegen/runtime v1.0.0 // indirect
+	github.com/olekukonko/tablewriter v0.0.5 // indirect
+	github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect
+	github.com/pierrec/lz4/v4 v4.1.15 // indirect
+	github.com/pkg/errors v0.8.1 // indirect
+	github.com/pmezard/go-difflib v1.0.0 // indirect
+	github.com/prometheus/client_model v0.5.0 // indirect
+	github.com/prometheus/common v0.45.0 // indirect
+	github.com/prometheus/procfs v0.12.0 // indirect
+	github.com/russross/blackfriday/v2 v2.1.0 // indirect
+	github.com/ryanuber/columnize v2.1.0+incompatible // indirect
+	github.com/sanity-io/litter v1.5.5 // indirect
+	github.com/schollz/closestmatch v2.1.0+incompatible // indirect
+	github.com/sergi/go-diff v1.1.0 // indirect
+	github.com/tdewolff/minify/v2 v2.20.6 // indirect
+	github.com/tdewolff/parse/v2 v2.7.4 // indirect
+	github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
+	github.com/valyala/bytebufferpool v1.0.0 // indirect
+	github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
+	github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
+	github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
+	github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
+	github.com/xeipuuv/gojsonschema v1.2.0 // indirect
+	github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect
+	github.com/yosssi/ace v0.0.5 // indirect
+	github.com/yudai/gojsondiff v1.0.0 // indirect
+	github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
+	go.etcd.io/etcd/api/v3 v3.5.11 // indirect
+	go.etcd.io/etcd/client/pkg/v3 v3.5.11 // indirect
+	go.opentelemetry.io/otel v1.0.0 // indirect
+	go.opentelemetry.io/otel/trace v1.0.0 // indirect
+	go.uber.org/atomic v1.7.0 // indirect
+	go.uber.org/multierr v1.6.0 // indirect
+	go.uber.org/zap v1.17.0 // indirect
+	golang.org/x/crypto v0.16.0 // indirect
+	golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
+	golang.org/x/sync v0.4.0 // indirect
+	golang.org/x/sys v0.15.0 // indirect
+	golang.org/x/text v0.14.0 // indirect
+	golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect
+	google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 // indirect
+	google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect
+	gopkg.in/ini.v1 v1.67.0 // indirect
+	gopkg.in/sourcemap.v1 v1.0.5 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+	launchpad.net/gocheck v0.0.0-20140225173054-000000000087 // indirect
+	moul.io/http2curl/v2 v2.3.0 // indirect
+)

+ 668 - 0
go.sum

@@ -0,0 +1,668 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
+github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c=
+github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
+github.com/CloudyKit/jet/v4 v4.1.0 h1:EvZLdRZYZ6iljADEhrfWSCSNOJRDntNqEJJmeP0Sjg0=
+github.com/CloudyKit/jet/v4 v4.1.0/go.mod h1:DhUsGNEpjPmBD0zmGNP8DaSV1dGO8g9U4adIK8BCWmw=
+github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME=
+github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4=
+github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
+github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM=
+github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
+github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc=
+github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
+github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk=
+github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM=
+github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
+github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
+github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
+github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0=
+github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM=
+github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
+github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
+github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
+github.com/andybalholm/brotli v1.0.1-0.20200619015827-c3da72aa01ed/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
+github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
+github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
+github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
+github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
+github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
+github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
+github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
+github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
+github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible h1:Ppm0npCCsmuR9oQaBtRuZcmILVE74aXE+AmrJj8L2ns=
+github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
+github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
+github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
+github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
+github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/chris-ramon/douceur v0.2.0/go.mod h1:wDW5xjJdeoMm1mRt4sD4c/LbF/mWdEpRXQKjTR8nIBE=
+github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28 h1:LdXxtjzvZYhhUaonAaAKArG3pyC67kGL3YY+6hGG8G4=
+github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
+github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
+github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
+github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
+github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
+github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
+github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
+github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=
+github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
+github.com/dgraph-io/badger/v2 v2.0.3/go.mod h1:3KY8+bsP8wI0OEnQJAKpd4wIJW/Mm32yw2j/9FUVnIM=
+github.com/dgraph-io/ristretto v0.0.2-0.20200115201040-8f368f2f2ab3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
+github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/eclipse/paho.mqtt.golang v1.4.3 h1:2kwcUGn8seMUfWndX0hGbvH8r7crgcJguQNCyp70xik=
+github.com/eclipse/paho.mqtt.golang v1.4.3/go.mod h1:CSYvoAlsMkhYOXh/oKyxa8EcBci6dVkLCbo5tTC1RIE=
+github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o=
+github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
+github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
+github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
+github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
+github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
+github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
+github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
+github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw=
+github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8=
+github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
+github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
+github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI=
+github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
+github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
+github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab h1:xveKWz2iaueeTaUgdetzel+U7exyigDYBryyVfV/rZk=
+github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
+github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
+github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
+github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
+github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
+github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
+github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
+github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
+github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
+github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
+github.com/gobwas/ws v1.0.3/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
+github.com/gobwas/ws v1.3.0 h1:sbeU3Y4Qzlb+MOzIe6mQGf7QR4Hkv6ZD0qhGkBFL2O0=
+github.com/gobwas/ws v1.3.0/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
+github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/gogf/gf v1.16.9 h1:Q803UmmRo59+Ws08sMVFOcd8oNpkSWL9vS33hlo/Cyk=
+github.com/gogf/gf v1.16.9/go.mod h1:8Q/kw05nlVRp+4vv7XASBsMe9L1tsVKiGoeP2AHnlkk=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
+github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
+github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
+github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
+github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
+github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
+github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386 h1:EcQR3gusLHN46TAD+G+EbaaqJArt5vHhNpXAa12PQf4=
+github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
+github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
+github.com/gomodule/redigo v1.8.5 h1:nRAxCa+SVsyjSBrtZmG/cqb6VbTmuRzpg/PoTFlpumc=
+github.com/gomodule/redigo v1.8.5/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
+github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
+github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/uuid v1.1.2-0.20200519141726-cb32006e483f/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
+github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
+github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
+github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
+github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
+github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
+github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI=
+github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk=
+github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
+github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/influxdata/influxdb-client-go/v2 v2.13.0 h1:ioBbLmR5NMbAjP4UVA5r9b5xGjpABD7j65pI8kFphDM=
+github.com/influxdata/influxdb-client-go/v2 v2.13.0/go.mod h1:k+spCbt9hcvqvUiz0sr5D8LolXHqAAOfPw9v/RIRHl4=
+github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU=
+github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
+github.com/iris-contrib/go.uuid v2.0.0+incompatible h1:XZubAYg61/JwnJNbZilGjf3b3pB80+OQg2qf6c8BfWE=
+github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0=
+github.com/iris-contrib/httpexpect/v2 v2.0.5/go.mod h1:JpRu+DEVVCA6KHLKUAs72QoaevQESqLHuG5s1CQ+QiA=
+github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go=
+github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE=
+github.com/iris-contrib/jade v1.1.4 h1:WoYdfyJFfZIUgqNAeOyRfTNQZOksSlZ6+FnXR3AEpX0=
+github.com/iris-contrib/jade v1.1.4/go.mod h1:EDqR+ur9piDl6DUgs6qRrlfzmlx/D5UybogqrXvJTBE=
+github.com/iris-contrib/middleware/cors v0.0.0-20231105204038-60b21ca77167 h1:zs9HA+Jn+NsbXTH6tER40sFDcnaFUtBljj5YAnwUfk4=
+github.com/iris-contrib/middleware/cors v0.0.0-20231105204038-60b21ca77167/go.mod h1:D/Xr6gLnI2E5jZJ6FC6pLiF1inXUWqnft6DibmTUuBo=
+github.com/iris-contrib/middleware/jwt v0.0.0-20231105204038-60b21ca77167 h1:x2POmaLt4fmAoO8ZvxrqLPRDtB7ZUiR5LC9ftNY8JYc=
+github.com/iris-contrib/middleware/jwt v0.0.0-20231105204038-60b21ca77167/go.mod h1:txkPY4oCyoRH302p0mx6IsAupinDtULtZ84V7L4dN+A=
+github.com/iris-contrib/pongo2 v0.0.1 h1:zGP7pW51oi5eQZMIlGA3I+FHY9/HOQWDB+572yin0to=
+github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g=
+github.com/iris-contrib/schema v0.0.2/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA=
+github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw=
+github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA=
+github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
+github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
+github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
+github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
+github.com/kataras/blocks v0.0.2/go.mod h1:KPyOYc1M3MgzsznVcdjErtcYWO3AZXQbQ8fMYWcr3oA=
+github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM=
+github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg=
+github.com/kataras/golog v0.0.18/go.mod h1:jRYl7dFYqP8aQj9VkwdBUXYZSfUktm+YYg1arJILfyw=
+github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20=
+github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A=
+github.com/kataras/iris v0.0.2 h1:Tteb6pXLN9QiXvTCXCP31LRHu1LHlVA6Rappr9vWa1c=
+github.com/kataras/iris v0.0.2/go.mod h1:ab8yy1jWHFgoI+/B+zoIsQpVY/XUY+NNvVCXJ27Zat8=
+github.com/kataras/iris/v12 v12.2.8 h1:p+PcqyO45dSib8B4I8Wc0fz+6B/CVkOsikCpbeNOkuo=
+github.com/kataras/iris/v12 v12.2.8/go.mod h1:on94BX0C5jhuxgWKDZVpcTqymksZDIxWFN+nL7axjRA=
+github.com/kataras/neffos v0.0.16/go.mod h1:BqWkF1c6cSyqw85dfCdqXxK5cMo/hyBGhtNuFkxHyMg=
+github.com/kataras/neffos v0.0.22 h1:3M4lHrUl//2OKmS9t9z3AKIZqwha6ABeA6WoF03HEv8=
+github.com/kataras/neffos v0.0.22/go.mod h1:IIJZcUDvwBxJGlDj942dqQgyznVKYDti91f8Ez+RRxE=
+github.com/kataras/pio v0.0.8/go.mod h1:NFfMp2kVP1rmV4N6gH6qgWpuoDKlrOeYi3VrAIWCGsE=
+github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM=
+github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM=
+github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8=
+github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY=
+github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4=
+github.com/kataras/tunnel v0.0.1/go.mod h1:Gslr6f+Y0esb704OqMi8hNOfFImgXcmg4KiN2zScgvs=
+github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA=
+github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
+github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
+github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
+github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
+github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
+github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw=
+github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/martini-contrib/binding v0.0.0-20160701174519-05d3e151b6cf h1:6YSkbjZVghliN7zwJC/U3QQG+OVXOrij3qQ8sxfPIMg=
+github.com/martini-contrib/binding v0.0.0-20160701174519-05d3e151b6cf/go.mod h1:aCggxkm1kuifLw/LEQUbz91N1ZM6PhV7dz03xPQduZA=
+github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11 h1:YFh+sjyJTMQSYjKwM4dFKhJPJC/wfo98tPUc17HdoYw=
+github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11/go.mod h1:Ah2dBMoxZEqk118as2T4u4fjfXarE0pPnMJaArZQZsI=
+github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
+github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
+github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA=
+github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
+github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
+github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
+github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
+github.com/mediocregopher/radix/v3 v3.5.0/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
+github.com/mediocregopher/radix/v3 v3.5.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
+github.com/mediocregopher/radix/v3 v3.8.1 h1:rOkHflVuulFKlwsLY01/M2cM2tWCjDoETcMqKbAWu1M=
+github.com/mediocregopher/radix/v3 v3.8.1/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
+github.com/microcosm-cc/bluemonday v1.0.3/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w=
+github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
+github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs=
+github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g=
+github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
+github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/nats-io/jwt v0.3.2 h1:+RB5hMpXUUA2dfxuhBTEkMOrYmM+gKIZYS1KjSostMI=
+github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
+github.com/nats-io/jwt/v2 v2.5.3 h1:/9SWvzc6hTfamcgXJ3uYRpgj+QuY2aLNqRiqrKcrpEo=
+github.com/nats-io/jwt/v2 v2.5.3/go.mod h1:iysuPemFcc7p4IoYots3IuELSI4EDe9Y0bQMe+I3Bf4=
+github.com/nats-io/nats-server/v2 v2.9.11 h1:4y5SwWvWI59V5mcqtuoqKq6L9NDUydOP3Ekwuwl8cZI=
+github.com/nats-io/nats-server/v2 v2.9.11/go.mod h1:b0oVuxSlkvS3ZjMkncFeACGyZohbO4XhSqW1Lt7iRRY=
+github.com/nats-io/nats.go v1.9.2/go.mod h1:AjGArbfyR50+afOUotNX2Xs5SYHf+CoOa5HH1eEl2HE=
+github.com/nats-io/nats.go v1.28.0 h1:Th4G6zdsz2d0OqXdfzKLClo6bOfoI/b1kInhRtFIy5c=
+github.com/nats-io/nats.go v1.28.0/go.mod h1:XpbWUlOElGwTYbMR7imivs7jJj9GtK7ypv321Wp6pjc=
+github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
+github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
+github.com/nats-io/nkeys v0.4.6 h1:IzVe95ru2CT6ta874rt9saQRkWfe2nFj1NtvYSLqMzY=
+github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADymtkpts=
+github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
+github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
+github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
+github.com/oapi-codegen/runtime v1.0.0 h1:P4rqFX5fMFWqRzY9M/3YF9+aPSPPB06IzP2P7oOxrWo=
+github.com/oapi-codegen/runtime v1.0.0/go.mod h1:LmCUMQuPB4M/nLXilQXhHw+BLZdDb18B34OO356yJ/A=
+github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
+github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
+github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
+github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
+github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
+github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
+github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
+github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
+github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
+github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
+github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0=
+github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
+github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28=
+github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
+github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
+github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
+github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
+github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
+github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
+github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
+github.com/robertkrimen/otto v0.3.0 h1:5RI+8860NSxvXywDY9ddF5HcPw0puRsd8EgbXV0oqRE=
+github.com/robertkrimen/otto v0.3.0/go.mod h1:uW9yN1CYflmUQYvAMS0m+ZiNo3dMzRUDQJX0jWbzgxw=
+github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
+github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
+github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
+github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
+github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
+github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/ryanuber/columnize v2.1.0+incompatible h1:j1Wcmh8OrK4Q7GXY+V7SVSY8nUWQxHW5TkBe7YUl+2s=
+github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
+github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
+github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
+github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
+github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk=
+github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
+github.com/segmentio/kafka-go v0.4.47 h1:IqziR4pA3vrZq7YdRxaT3w1/5fvIH5qpCwstUanQQB0=
+github.com/segmentio/kafka-go v0.4.47/go.mod h1:HjF6XbOKh0Pjlkr5GVZxt6CsjjwnmhVOfURM5KMd8qg=
+github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
+github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
+github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
+github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
+github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
+github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
+github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
+github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
+github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
+github.com/square/go-jose/v3 v3.0.0-20200630053402-0a67ce9b0693/go.mod h1:6hSY48PjDm4UObWmGLyJE9DxYVKTgR9kbCspXXJEhcU=
+github.com/streadway/amqp v1.1.0 h1:py12iX8XSyI7aN/3dUT8DFIDJazNJsVJdxNVEpnQTZM=
+github.com/streadway/amqp v1.1.0/go.mod h1:WYSrTEYHOXHd0nwFeUXAe2G2hRnQT+deZJJf88uS9Bg=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8=
+github.com/tdewolff/minify/v2 v2.20.6 h1:R4+Iw1ZqJxrqH52WWHtCpukMuhmO/EasY8YlDiSxphw=
+github.com/tdewolff/minify/v2 v2.20.6/go.mod h1:9t0EY9xySGt1vrP8iscmJfywQwDCQyQBYN6ge+9GwP0=
+github.com/tdewolff/parse/v2 v2.7.4 h1:zrUn2CFg9+5llbUZcsycctFlNRyV1D5gFBZRxuGzdzk=
+github.com/tdewolff/parse/v2 v2.7.4/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA=
+github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52 h1:gAQliwn+zJrkjAHVcBEYW/RFvd2St4yYimisvozAYlA=
+github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
+github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o=
+github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
+github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg=
+github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
+github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
+github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/vmihailenco/msgpack/v4 v4.3.11/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
+github.com/vmihailenco/msgpack/v5 v5.0.0-beta.1/go.mod h1:xlngVLeyQ/Qi05oQxhQ+oTuqa03RjMwMfk/7/TCs+QI=
+github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
+github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
+github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
+github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
+github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
+github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
+github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
+github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
+github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
+github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
+github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
+github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
+github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
+github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
+github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
+github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
+github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
+github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
+github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY=
+github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
+github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA=
+github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0=
+github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
+github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
+github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
+github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
+github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI=
+github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
+go.etcd.io/etcd/api/v3 v3.5.11 h1:B54KwXbWDHyD3XYAwprxNzTe7vlhR69LuBgZnMVvS7E=
+go.etcd.io/etcd/api/v3 v3.5.11/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4=
+go.etcd.io/etcd/client/pkg/v3 v3.5.11 h1:bT2xVspdiCj2910T0V+/KHcVKjkUrCZVtk8J2JF2z1A=
+go.etcd.io/etcd/client/pkg/v3 v3.5.11/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4=
+go.etcd.io/etcd/client/v3 v3.5.11 h1:ajWtgoNSZJ1gmS8k+icvPtqsqEav+iUorF7b0qozgUU=
+go.etcd.io/etcd/client/v3 v3.5.11/go.mod h1:a6xQUEqFJ8vztO1agJh/KQKOMfFI8og52ZconzcDJwE=
+go.opentelemetry.io/otel v1.0.0 h1:qTTn6x71GVBvoafHK/yaRUmFzI4LcONZD0/kXxl5PHI=
+go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
+go.opentelemetry.io/otel/trace v1.0.0 h1:TSBr8GTEtKevYMG/2d21M989r5WJYVimhTHBKVEZuh4=
+go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
+go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
+go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
+go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U=
+go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
+golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
+golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
+golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/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-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
+golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
+golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
+golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/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-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+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.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
+golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-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.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
+golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
+golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+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.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
+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.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
+golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
+golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f h1:GGU+dLjvlC3qDwqYgL6UgRmHXhOOgns0bZu2Ty5mm6U=
+golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
+gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
+gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
+gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0=
+google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk=
+google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU=
+google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
+google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
+google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
+gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
+gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
+gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+labix.org/v2/mgo v0.0.0-20140701140051-000000000287 h1:L0cnkNl4TfAXzvdrqsYEmxOHOCv2p5I3taaReO8BWFs=
+labix.org/v2/mgo v0.0.0-20140701140051-000000000287/go.mod h1:Lg7AYkt1uXJoR9oeSZ3W/8IXLdvOfIITgZnommstyz4=
+launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54=
+launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=
+moul.io/http2curl v1.0.0/go.mod h1:f6cULg+e4Md/oW1cYmwW4IWQOVl2lGbmCNGOHvzX2kE=
+moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs=
+moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE=
+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

+ 1 - 1
install.sh

@@ -1,3 +1,3 @@
-export GO111MODULE=off
+export GO111MODULE=on
 cd services
 go install -v ./...

+ 3 - 4
pkg/mqtt/connection.go

@@ -205,10 +205,9 @@ func (c *Connection) RcvMsgFromClient() {
 				return
 			}
 			args := rpcs.ArgsGetOnline{
-				Id:            device.DeviceIdentifier,
-				ClientIP:      host,
-				AccessRPCHost: server.GetRPCHost(),
-				//HeartbeatInterval: uint32(c.KeepAlive),
+				Id:                device.DeviceIdentifier,
+				ClientIP:          host,
+				AccessRPCHost:     server.GetRPCHost(),
 				HeartbeatInterval: 300,
 			}
 

+ 13 - 2
pkg/online/online.go

@@ -21,14 +21,14 @@ type Manager struct {
 }
 
 func NewManager(host string, port, db int) *Manager {
-	gredis.SetConfig(gredis.Config{
+	red := gredis.New(&gredis.Config{
 		Host:      host,
 		Port:      port,
 		Db:        db,
 		MaxActive: 100,
 	})
 	mgr := &Manager{
-		redisClient: gredis.Instance(),
+		redisClient: red,
 	}
 	return mgr
 }
@@ -63,6 +63,17 @@ func (mgr *Manager) GetOnline(id string, status Status) error {
 	return nil
 }
 
+func (mgr *Manager) GetOnlineV2(id string, status Status) error {
+	key := KeyPrefix + id
+	buffStr := gconv.String(&status)
+	_, err := mgr.redisClient.Do("SET", key, buffStr)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
 func (mgr *Manager) SetHeartbeat(id string) error {
 	status, err := mgr.GetStatus(id)
 	if err != nil {

+ 9 - 0
pkg/protocol/emqx_device.go

@@ -0,0 +1,9 @@
+package protocol
+
+type DevConnectStatus struct {
+	DeviceCode string
+	Reason     string
+	Action     string
+	DeviceId   string
+	ClientIp   string
+}

+ 128 - 0
pkg/protocol/topic.go

@@ -0,0 +1,128 @@
+package protocol
+
+import (
+	"errors"
+	"fmt"
+	"strings"
+)
+
+/*
+物理型topic:
+$thing/up/status/${productID}/${deviceName}	发布	属性上报
+$thing/down/status/${productID}/${deviceName}	订阅	属性下发与属性上报响应
+$thing/up/event/${productID}/${deviceName}	发布	事件上报
+$thing/down/event/${productID}/${deviceName}	订阅	事件上报响应
+$thing/up/command/${productID}/${deviceName}	发布	设备响应行为执行结果
+$thing/down/command/${productID}/${deviceName}	订阅	应用调用设备行为
+系统级topic:
+$ota/report/${productID}/${deviceName}	发布	固件升级消息上行
+$ota/update/${productID}/${deviceName}	订阅	固件升级消息下行
+$broadcast/rxd/${productID}/${deviceName}	订阅	广播消息下行
+$shadow/operation/up/{productID}/${deviceName}	发布	设备影子消息上行
+$shadow/operation/down/{productID}/${deviceName}	订阅	设备影子消息下行
+$rrpc/txd/{productID}/${deviceName}/${MessageId}	发布	RRPC消息上行,MessageId为RRPC消息ID
+$rrpc/rxd/{productID}/${deviceName}/+	订阅	RRPC消息下行
+$sys/operation/up/{productID}/${deviceName}	发布	系统topic:ntp服务消息上行
+$sys/operation/down/{productID}/${deviceName}/+	订阅	系统topic:ntp服务消息下行
+log topic
+$log/up/operation/${productID}/${deviceName} //设备查询是否需要上传调试日志及日志级别,上行
+$log/down/operation/${productID}/${deviceName}
+$log/up/report/${productID}/${deviceName} //设备上传调试日志内容,上行
+$log/down/report/${productID}/${deviceName}
+$log/down/update/${productID}/${deviceName} //服务器端下发调试日志配置,下行
+
+自定义topic:
+${productID}/${deviceName}/control	订阅	编辑删除
+${productID}/${deviceName}/data	订阅和发布	编辑删除
+${productID}/${deviceName}/event	发布
+${productID}/${deviceName}/xxxxx	订阅和发布   //自定义 暂不做支持
+*/
+const (
+	TopicHeadThing   = "$thing"
+	Thing            = "thing"
+	TopicHeadOta     = "$ota"
+	Ota              = "ota"
+	TopicHeadConfig  = "$config"
+	Config           = "config"
+	TopicHeadLog     = "$log"
+	Log              = "log"
+	TopicHeadShadow  = "$shadow"
+	Shadow           = "shadow"
+	TopicHeadGateway = "$gateway"
+	Gateway          = "gateway"
+	TopicHeadExt     = "$ext"
+	Ext              = "ext"
+)
+
+type Direction int
+
+const (
+	Unknown Direction = iota //设备通信流向:未知
+	Up                       //设备通信流向:上行
+	Down                     //设备通信流向:下行
+)
+
+type TopicInfo struct {
+	ProductKey string
+	DeviceCode string
+	Direction  Direction
+	Types      []string
+	TopicHead  string
+}
+
+func GetTopicInfo(topic string) (topicInfo *TopicInfo, err error) {
+	keys := strings.Split(topic, "/")
+	return parseTopic(keys)
+}
+func parseTopic(topics []string) (topicInfo *TopicInfo, err error) {
+	if len(topics) < 2 {
+		return nil, errors.New("topic is err")
+	}
+	switch topics[0] {
+	case TopicHeadThing, TopicHeadOta, TopicHeadShadow, TopicHeadLog, TopicHeadConfig, TopicHeadGateway, TopicHeadExt:
+		return parseLast(topics)
+	default: //自定义消息
+		return parsePose(0, topics)
+	}
+}
+func parsePose(productPos int, topics []string) (topicInfo *TopicInfo, err error) {
+	return nil, errors.New("topic is err")
+	//先不考虑自定义消息
+	//if len(topics) < (productPos + 2) {
+	//	return nil, errors.Parameter.AddDetail("topic is err")
+	//}
+	//return &TopicInfo{
+	//	ProductID:  topics[productPos],
+	//	DeviceName: topics[productPos+1],
+	//	TopicHead:  topics[0],
+	//}, err
+}
+func parseLast(topics []string) (topicInfo *TopicInfo, err error) {
+	if len(topics) < 4 {
+		return nil, errors.New("topic is err")
+	}
+	return &TopicInfo{
+		ProductKey: topics[len(topics)-2],
+		DeviceCode: topics[len(topics)-1],
+		Direction:  getDirection(topics[1]),
+		Types:      topics[2 : len(topics)-2],
+		TopicHead:  topics[0],
+	}, err
+}
+
+func GetCommandTopic(deviceCode, productKey string) string {
+	topic := strings.Join([]string{TopicHeadThing, "down", "command", productKey, deviceCode}, "/")
+	fmt.Printf("topic:%s\r\n", topic)
+	return topic
+}
+
+func getDirection(dir string) Direction {
+	switch dir {
+	case "up":
+		return Up
+	case "down":
+		return Down
+	default:
+		return Unknown
+	}
+}

+ 7 - 6
pkg/rpcs/common.go

@@ -8,10 +8,11 @@ type ReplyEmptyResult struct{}
 
 // 定义 rpc服务的名字
 const (
-	RegistryServerName = "registry"
-	MQTTAccessName     = "MQTTAccess"
-	DeviceManagerName  = "deviceManager"
-	ControllerName     = "controller"
-	HttpAccessName     = "HTTPAccess"
-	ShadowServiceName  = "ShadowServer"
+	RegistryServerName   = "registry"
+	MQTTAccessName       = "MQTTAccess"
+	DeviceManagerName    = "deviceManager"
+	ControllerName       = "controller"
+	HttpAccessName       = "HTTPAccess"
+	ShadowServiceName    = "ShadowServer"
+	EmqxAgentServiceName = "EmqxAgentServer"
 )

+ 4 - 5
pkg/ruleEngine/nodes/mqtt_broker_node.go

@@ -3,7 +3,7 @@ package nodes
 import (
 	"encoding/json"
 	"fmt"
-	MQTT "git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git"
+	MQTT "github.com/eclipse/paho.mqtt.golang"
 	"github.com/gogf/gf/util/guid"
 	"html/template"
 	"sparrow/pkg/protocol"
@@ -18,9 +18,9 @@ const defaultTimeout = 5
 
 // MQTTBrokerNode Publish incoming message payload to the topic of the configured MQTT broker with QoS AT_LEAST_ONCE.
 // In case of successful message publishing, original Message will be passed to the next nodes via Success chain,
-//otherwise Failure chain is used.
+// otherwise Failure chain is used.
 type MQTTBrokerNode struct {
-	mqttClient *MQTT.Client
+	mqttClient MQTT.Client
 	config     *MQTTBrokerNodeCfg
 }
 
@@ -71,7 +71,7 @@ func (M *MQTTBrokerNode) Init(ctx ruleEngine.Context, config string) error {
 	var opt MQTT.ClientOptions
 	opt.ClientID = "MQTT_NODE_" + guid.S()
 	opt.CleanSession = M.config.ClearSession
-	opt.KeepAlive = time.Second * 30
+	opt.KeepAlive = 30
 	opt.ConnectTimeout = time.Duration(M.config.Timeout) * time.Second
 	switch M.config.Credentials {
 	case "Basic":
@@ -88,7 +88,6 @@ func (M *MQTTBrokerNode) Init(ctx ruleEngine.Context, config string) error {
 	opt.AddBroker(fmt.Sprintf("tcp://%s:%d", M.config.Host, M.config.Port))
 	c := MQTT.NewClient(&opt)
 	M.mqttClient = c
-	fmt.Printf("M.mqttClient = c:%v\r\n", c)
 	go func() {
 		if token := c.Connect(); token.Wait() && token.Error() != nil {
 			return

+ 1 - 1
pkg/server/config.go

@@ -22,7 +22,7 @@ const (
 )
 
 var (
-	confUDPHost = flag.String(FlagUDPHost, "", "udp server listen address, format ip:port")
+	confUDPHost = flag.String(FlagUDPHost, "", "udp server listen address, format ip:port ")
 	confTCPHost = flag.String(FlagTCPHost, "", "tcp server listen address, format ip:port")
 	confUseTls  = flag.Bool(FlagUseTls, false, "if tcp server uses tls, default false")
 

+ 1 - 1
pkg/server/log.go

@@ -3,7 +3,7 @@
 package server
 
 import (
-	"github.com/Sirupsen/logrus"
+	"github.com/sirupsen/logrus"
 )
 
 var Log *logrus.Entry

+ 1 - 2
pkg/server/server.go

@@ -8,9 +8,8 @@ package server
 
 import (
 	"context"
-	"github.com/opentracing/opentracing-go"
-	// "github.com/vharitonsky/iniflags"
 	"flag"
+	"github.com/opentracing/opentracing-go"
 	"net/http"
 	"net/rpc"
 	"sparrow/pkg/tracing"

+ 2 - 3
pkg/server/server_manager.go

@@ -5,13 +5,12 @@ package server
 import (
 	"errors"
 	"fmt"
-	"go.etcd.io/etcd/clientv3"
+	clientv3 "go.etcd.io/etcd/client/v3"
+	"golang.org/x/net/context"
 	"os"
 	"strings"
 	"sync"
 	"time"
-
-	"golang.org/x/net/context"
 )
 
 const (

+ 9 - 9
pkg/tlv/tlv_test.go

@@ -70,15 +70,15 @@ func TestTlvLen(t *testing.T) {
 	}
 }
 
-func TestUintAndByte(t *testing.T) {
-	value := uint16(100)
-	byteValue := Uint16ToByte(value)
-	newValue := ByteToUint16(byteValue)
-
-	if value != newValue {
-		t.Errorf("origin: %d, now: %d\n", value, newValue)
-	}
-}
+//func TestUintAndByte(t *testing.T) {
+//	value := uint16(100)
+//	byteValue := Uint16ToByte(value)
+//	newValue := ByteToUint16(byteValue)
+//
+//	if value != newValue {
+//		t.Errorf("origin: %d, now: %d\n", value, newValue)
+//	}
+//}
 
 func TestTlvs(t *testing.T) {
 	str := "itachili"

+ 2 - 2
pkg/token/token.go

@@ -19,14 +19,14 @@ type Helper struct {
 }
 
 func NewHelper(host string, port, db int) *Helper {
-	gredis.SetConfig(gredis.Config{
+	red := gredis.New(&gredis.Config{
 		Host:      host,
 		Port:      port,
 		Db:        db,
 		MaxActive: 100,
 	})
 	helper := &Helper{
-		redisClient: gredis.Instance(),
+		redisClient: red,
 	}
 	return helper
 }

+ 1 - 1
pkg/utils/util.go

@@ -47,6 +47,6 @@ func Exists(filename string) (bool, error) {
 
 // UUID uuid
 func UUID() string {
-	s, _ := uuid.NewV4()
+	s := uuid.NewV4()
 	return s.String()
 }

BIN
services/.DS_Store


+ 37 - 0
services/apiprovider/actions.go

@@ -272,6 +272,43 @@ func SendCommandToDevice(device *models.Device, config *productconfig.ProductCon
 
 }
 
+func SendCommandToDeviceV2(device *models.Device, config *productconfig.ProductConfig,
+	urlparams martini.Params, req *http.Request, r render.Render) {
+	timeout := req.URL.Query().Get("timeout")
+
+	server.Log.Printf("ACTION SendCommandToDevice, identifier:: %v, request: %v, timeout: %v",
+		device.DeviceIdentifier, req.Body, timeout)
+
+	var args map[string]interface{}
+	decoder := json.NewDecoder(req.Body)
+	err := decoder.Decode(&args)
+	if err != nil {
+		r.JSON(http.StatusOK, renderError(ErrWrongRequestFormat, err))
+		return
+	}
+
+	j := gjson.New(args)
+	cmdargs := rpcs.ArgsSendCommand{
+		DeviceId:  device.DeviceIdentifier,
+		SubDevice: j.GetString("subDeviceId"),
+		WaitTime:  uint32(defaultTimeOut),
+		Params:    j.GetMap("data.params"),
+		Cmd:       j.GetString("data.cmd"),
+	}
+	cmdreply := rpcs.ReplySendCommand{}
+
+	err = server.RPCCallByName(context.Background(), rpcs.ControllerName, "Controller.SendCommandV2", cmdargs, &cmdreply)
+	if err != nil {
+		server.Log.Errorf("send devie command error: %v", err)
+		r.JSON(http.StatusOK, renderError(ErrSystemFault, err))
+		return
+	}
+
+	r.JSON(http.StatusOK, Common{})
+	return
+
+}
+
 // AddRule 增加设备规则
 func AddRule(device *models.Device, req *http.Request, r render.Render) {
 	var ruleReq CreateRuleRequest

+ 6 - 0
services/apiprovider/router.go

@@ -67,6 +67,12 @@ func route(m *martini.ClassicMartini) {
 
 		r.Get("/devices/online", CheckDeviceIsOnline)
 	})
+	m.Group("/application/v2", func(r martini.Router) {
+		// send a command to device
+		r.Post("/devices/:identifier/commands",
+			ApplicationAuthOnDeviceIdentifer, CheckDeviceOnline, CheckProductConfig,
+			SendCommandToDeviceV2)
+	})
 
 	m.Post("/application/auth", AppAuth)
 

+ 9 - 0
services/controller/controller.go

@@ -295,6 +295,15 @@ func (c *Controller) SendCommand(args rpcs.ArgsSendCommand, reply *rpcs.ReplySen
 	return server.RPCCallByHost(rpchost, "Access.SendCommand", args, reply)
 }
 
+// SendCommandV2 下发设备控制指令适配emqx
+func (c *Controller) SendCommandV2(args rpcs.ArgsSendCommand, reply *rpcs.ReplySendCommand) error {
+	rpchost, err := getAccessRPCHost(args.DeviceId)
+	if err != nil {
+		return err
+	}
+	return server.RPCCallByHost(rpchost, "Agent.SendCommand", args, reply)
+}
+
 func getAccessRPCHost(deviceid string) (string, error) {
 	args := rpcs.ArgsGetDeviceOnlineStatus{
 		Id: deviceid,

+ 8 - 1
services/devicemanager/manager.go

@@ -31,7 +31,6 @@ func (dm *DeviceManager) GenerateDeviceAccessToken(args rpcs.ArgsGenerateDeviceA
 }
 
 func (dm *DeviceManager) ValidateDeviceAccessToken(args rpcs.ArgsValidateDeviceAccessToken, reply *rpcs.ReplyValidateDeviceAccessToken) error {
-	dm.onlineManager.SetHeartbeat(args.Id)
 	return dm.tokenHelper.ValidateToken(args.Id, args.AccessToken)
 }
 
@@ -43,6 +42,14 @@ func (dm *DeviceManager) GetOnline(args rpcs.ArgsGetOnline, reply *rpcs.ReplyGet
 	})
 }
 
+func (dm *DeviceManager) GetOnlineV2(args rpcs.ArgsGetOnline, reply *rpcs.ReplyGetOnline) error {
+	return dm.onlineManager.GetOnlineV2(args.Id, online.Status{
+		ClientIP:          args.ClientIP,
+		AccessRPCHost:     args.AccessRPCHost,
+		HeartbeatInterval: args.HeartbeatInterval,
+	})
+}
+
 func (dm *DeviceManager) HeartBeat(args rpcs.ArgsHeartBeat, reply *rpcs.ReplyHeartBeat) error {
 	return dm.onlineManager.SetHeartbeat(args.Id)
 }

+ 260 - 0
services/emqx-agent/agent.go

@@ -0,0 +1,260 @@
+package main
+
+import (
+	"context"
+	"github.com/gogf/gf/encoding/gjson"
+	"sparrow/pkg/klink"
+	"sparrow/pkg/models"
+	"sparrow/pkg/protocol"
+	"sparrow/pkg/rpcs"
+	"sparrow/pkg/server"
+	"time"
+)
+
+type Agent struct {
+	client SubDev
+}
+
+// Message 收到设备上报消息处理
+func (a *Agent) Message(topic string, payload []byte) error {
+
+	topicInfo, err := protocol.GetTopicInfo(topic)
+	if err != nil {
+		return err
+	}
+	if topicInfo.Direction == protocol.Down {
+		return nil
+	}
+	device := &models.Device{}
+	err = server.RPCCallByName(nil, rpcs.RegistryServerName, "Registry.FindDeviceByIdentifier", topicInfo.DeviceCode, device)
+	if err != nil {
+		server.Log.Errorf("device not found %s", topicInfo.DeviceCode)
+		return nil
+	}
+	server.Log.Debugf("device {%v} message {%v} : %s", device.DeviceIdentifier, topicInfo.Types, payload)
+	if len(topicInfo.Types) == 0 {
+		return nil
+	}
+	jsonPayload, err := gjson.DecodeToJson(payload)
+	if err != nil {
+		return nil
+	}
+
+	switch topicInfo.Types[0] {
+	case "status":
+		return a.processStatus(topicInfo.DeviceCode, device.VendorID, jsonPayload)
+	case "event":
+		return a.processEvent(topicInfo.DeviceCode, device.VendorID, jsonPayload)
+	}
+	return nil
+}
+
+func (a *Agent) processEvent(deviceId, vendorId string, message *gjson.Json) error {
+	reply := rpcs.ReplyOnEvent{}
+	args := rpcs.ArgsOnEvent{
+		DeviceId:    deviceId,
+		TimeStamp:   message.GetUint64("timestamp"),
+		SubDeviceId: message.GetString("subDeviceId"),
+		SubData:     message.GetJson("data").MustToJson(),
+		VendorId:    vendorId,
+	}
+	err := server.RPCCallByName(nil, rpcs.ControllerName, "Controller.OnEvent", args, &reply)
+	if err != nil {
+		server.Log.Errorf("device on event error. args: %v, error: %v", args, err)
+		return err
+	}
+	return nil
+}
+
+func (a *Agent) processStatus(deviceId, vendorId string, message *gjson.Json) error {
+	act := klink.PacketAction(message.GetString("action"))
+	if act != "" {
+		switch act {
+		case klink.DevSendAction:
+			processReportStatus(deviceId, vendorId, message)
+		case klink.DevLoginAction:
+			_ = processDevLogin(deviceId, message.GetString("subDeviceId"))
+		case klink.DevLogoutAction:
+			_ = processDevLogout(deviceId, message.GetString("subDeviceId"))
+		case klink.DevNetConfigAction:
+			_ = processDevNetConfig(deviceId, message.GetString("md5"))
+		case klink.ReportFirmwareAction:
+			_ = processDeviceReportUpgrade(deviceId, message.GetString("version"))
+		}
+	}
+	return nil
+}
+func processDevLogin(deviceCode, subDeviceId string) error {
+	var args rpcs.SubDeviceArgs
+	args.DeviceCode = deviceCode
+	args.Status = 1
+	args.SubDeviceId = subDeviceId
+	var reply *models.SubDevice
+	err := server.RPCCallByName(context.Background(), rpcs.RegistryServerName, "Registry.UpdateSubDevice", &args, &reply)
+	if err != nil {
+		server.Log.Errorf("子设备上线出错:%s", err.Error())
+	}
+	return nil
+}
+
+func processDevLogout(deviceCode, subDeviceId string) error {
+	var args rpcs.SubDeviceArgs
+	args.DeviceCode = deviceCode
+	args.Status = 0
+	args.SubDeviceId = subDeviceId
+	var reply *models.SubDevice
+	err := server.RPCCallByName(context.Background(), rpcs.RegistryServerName, "Registry.UpdateSubDevice", &args, &reply)
+	if err != nil {
+		server.Log.Errorf("子设备下线出错:%s", err.Error())
+	}
+	return nil
+}
+
+// 处理设备配网信息
+func processDevNetConfig(deviceCode, md5 string) error {
+	args := &models.DeviceNetConfig{
+		DeviceIdentifier: deviceCode,
+		MD5:              md5,
+		Status:           1,
+	}
+	reply := rpcs.ReplyCheckDeviceNetConfig{}
+	err := server.RPCCallByName(nil, rpcs.RegistryServerName, "Registry.CreateDeviceNetConfig", args, &reply)
+	if err != nil {
+		server.Log.Errorf("set device:%s net config info error:%v", deviceCode, err)
+	}
+	return nil
+}
+
+// 设备上报固件信息处理
+func processDeviceReportUpgrade(deviceId, version string) error {
+	args := &rpcs.ArgsUpdateDeviceVersion{
+		DeviceId: deviceId,
+		Version:  version,
+	}
+	var reply rpcs.ReplyEmptyResult
+	err := server.RPCCallByName(nil, rpcs.RegistryServerName, "Registry.UpdateDeviceVersion", args, &reply)
+	if err != nil {
+		server.Log.Errorf("更新设备版本号失败:%v", err)
+	}
+	return nil
+}
+func processReportStatus(deviceid, vendorId string, message *gjson.Json) {
+	reply := rpcs.ReplyOnStatus{}
+	args := rpcs.ArgsOnStatus{
+		DeviceId:    deviceid,
+		Timestamp:   message.GetUint64("timestamp"),
+		SubData:     message.GetJson("data").MustToJson(),
+		VendorId:    vendorId,
+		SubDeviceId: message.GetString("subDeviceId"),
+		Action:      klink.PacketAction(message.GetString("action")),
+	}
+	err := server.RPCCallByName(nil, rpcs.ControllerName, "Controller.OnStatus", args, &reply)
+	if err != nil {
+		server.Log.Errorf("device report status error. args: %v, error: %v", args, err)
+		return
+	}
+}
+
+// Connected 设备接入时
+func (a *Agent) Connected(status *protocol.DevConnectStatus) error {
+	// 查询设备信息
+	device := &models.Device{}
+	err := server.RPCCallByName(nil, rpcs.RegistryServerName, "Registry.FindDeviceByIdentifier", status.DeviceId, device)
+	if err != nil {
+		server.Log.Errorf("device not found %s", status.DeviceId)
+		return nil
+	}
+	args := rpcs.ArgsGetOnline{
+		Id:                device.DeviceIdentifier,
+		ClientIP:          status.ClientIp,
+		AccessRPCHost:     server.GetRPCHost(),
+		HeartbeatInterval: 300,
+	}
+	reply := rpcs.ReplyGetOnline{}
+	err = server.RPCCallByName(nil, rpcs.DeviceManagerName, "DeviceManager.GetOnlineV2", args, &reply)
+	if err != nil {
+		server.Log.Errorf("device online error. args: %v, error: %v", args, err)
+	}
+	var cReply rpcs.ReplyEmptyResult
+	var cArgs rpcs.ArgsGetStatus
+	cArgs.VendorId = device.VendorID
+	cArgs.Id = args.Id
+	if err = server.RPCCallByName(nil, rpcs.ControllerName, "Controller.Online", &cArgs, &cReply); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Disconnected 设备断开连接时
+func (a *Agent) Disconnected(status *protocol.DevConnectStatus) error {
+	// 查询设备信息
+	device := &models.Device{}
+	err := server.RPCCallByName(nil, rpcs.RegistryServerName, "Registry.FindDeviceByIdentifier", status.DeviceId, device)
+	if err != nil {
+		server.Log.Errorf("device not found %s", status.DeviceId)
+		return nil
+	}
+	args := rpcs.ArgsGetOffline{
+		Id:       device.DeviceIdentifier,
+		VendorId: device.VendorID,
+	}
+	reply := rpcs.ReplyGetOffline{}
+	err = server.RPCCallByName(nil, rpcs.DeviceManagerName, "DeviceManager.GetOffline", args, &reply)
+	if err != nil {
+		server.Log.Errorf("device offline error. deviceid: %v, error: %v", status.DeviceId, err)
+	}
+	return err
+}
+
+// SendCommand rpc 发送设备命令
+func (a *Agent) SendCommand(args rpcs.ArgsSendCommand, reply *rpcs.ReplySendCommand) error {
+	// 查询设备信息
+	device := &models.Device{}
+	err := server.RPCCallByName(nil, rpcs.RegistryServerName, "Registry.FindDeviceByIdentifier", args.DeviceId, device)
+	if err != nil {
+		server.Log.Errorf("device not found %s", args.DeviceId)
+		return nil
+	}
+	product := &models.Product{}
+	err = server.RPCCallByName(nil, rpcs.RegistryServerName, "Registry.FindProduct", device.ProductID, product)
+	if err != nil {
+		server.Log.Errorf("device not found %s", args.DeviceId)
+		return nil
+	}
+	cmd := &klink.CloudSend{
+		Action:      "cloudSend",
+		MsgId:       0,
+		DeviceCode:  args.DeviceId,
+		SubDeviceId: args.SubDevice,
+		Timestamp:   time.Now().Unix(),
+		Data: &klink.CloudSendData{
+			Cmd:    args.Cmd,
+			Params: args.Params,
+		},
+	}
+	msg, err := cmd.Marshal()
+	if err != nil {
+		return err
+	}
+	return a.client.PublishToMsgToDev(protocol.GetCommandTopic(args.DeviceId, product.ProductKey), msg)
+}
+
+// GetStatus rpc 获取设备状态
+func (a *Agent) GetStatus(args rpcs.ArgsGetStatus, reply *rpcs.ReplyGetStatus) error {
+	server.Log.Infof("Access Get Status: %v", args)
+	// first send a get status command
+	cmdArgs := rpcs.ArgsSendCommand{
+		DeviceId:  args.Id,
+		WaitTime:  0,
+		SubDevice: args.SubDeviceId,
+		Cmd:       "report",
+	}
+	cmdReply := rpcs.ReplySendCommand{}
+	return a.SendCommand(cmdArgs, &cmdReply)
+}
+
+func NewAgent(client SubDev) *Agent {
+	return &Agent{
+		client: client,
+	}
+}

+ 9 - 0
services/emqx-agent/client/config.go

@@ -0,0 +1,9 @@
+package client
+
+type MqttConfig struct {
+	ClientId string
+	Brokers  []string
+	User     string
+	Password string
+	ConnNum  int
+}

+ 99 - 0
services/emqx-agent/client/mqtt_client.go

@@ -0,0 +1,99 @@
+package client
+
+import (
+	"crypto/tls"
+	"fmt"
+	MQTT "github.com/eclipse/paho.mqtt.golang"
+	"github.com/gogf/gf/util/guid"
+	"math/rand"
+	"net/url"
+	"sparrow/pkg/server"
+
+	"sync"
+	"time"
+)
+
+var (
+	mqttInitOnce            sync.Once
+	mqttClient              *MqttClient
+	mqttSetOnConnectHandler func(cli MQTT.Client)
+)
+
+type MqttClient struct {
+	clients []MQTT.Client
+}
+
+func NewMqttClient(conf *MqttConfig) (mcs *MqttClient, err error) {
+	mqttInitOnce.Do(func() {
+		var clients []MQTT.Client
+		for len(clients) < conf.ConnNum {
+			var (
+				mc MQTT.Client
+			)
+			for i := 3; i > 0; i-- {
+				mc, err = initMqttClient(conf)
+				if err != nil {
+					server.Log.Errorf("init mqtt client failed: %s", err.Error())
+					continue
+				}
+				break
+			}
+			if err != nil {
+				server.Log.Errorf("mqtt 连接失败: %s", err.Error())
+				panic(err)
+			}
+			clients = append(clients, mc)
+			var cli = MqttClient{clients: clients}
+			mqttClient = &cli
+		}
+	})
+	return mqttClient, err
+}
+
+func initMqttClient(conf *MqttConfig) (mc MQTT.Client, err error) {
+	opts := MQTT.NewClientOptions()
+	for _, broker := range conf.Brokers {
+		opts.AddBroker(broker)
+	}
+	opts.SetClientID(fmt.Sprintf("%s_%s", conf.ClientId, guid.S())).
+		SetUsername(conf.User).SetPassword(conf.Password).
+		SetConnectRetry(true)
+	opts.SetConnectionAttemptHandler(func(broker *url.URL, tlsCfg *tls.Config) *tls.Config {
+		server.Log.Infof("connect to %s", broker.String())
+		return tlsCfg
+	})
+	opts.SetOnConnectHandler(func(client MQTT.Client) {
+		server.Log.Infof("connected success")
+	})
+
+	mc = MQTT.NewClient(opts)
+	if errF := mc.Connect().WaitTimeout(time.Second * 5); errF == false {
+		server.Log.Errorf("connected failed")
+		return
+	}
+	return
+}
+
+// Subscribe 订阅消息
+func (m MqttClient) Subscribe(cli MQTT.Client, topic string, qos byte, callback MQTT.MessageHandler) error {
+	var clients = m.clients
+	if cli != nil {
+		clients = []MQTT.Client{cli}
+	}
+	for _, client := range clients {
+		err := client.Subscribe(topic, qos, callback).Error()
+		if err != nil {
+			server.Log.Errorf("subscribe failed: %s", err.Error())
+		}
+	}
+	return nil
+}
+
+// Publish 发布消息
+func (m MqttClient) Publish(topic string, qos byte, retained bool, payload interface{}) error {
+	id := rand.Intn(len(m.clients))
+	return m.clients[id].Publish(topic, qos, retained, payload).Error()
+}
+func SetMqttSetOnConnectHandler(f func(cli MQTT.Client)) {
+	mqttSetOnConnectHandler = f
+}

+ 6 - 0
services/emqx-agent/config.toml

@@ -0,0 +1,6 @@
+[mqtt]
+client_id = "sparrow"
+brokers = ["114.115.251.196:1883"]
+user = "sparrow_test"
+password = "sparrow_test"
+conn_number = 10

+ 264 - 0
services/emqx-agent/main.go

@@ -0,0 +1,264 @@
+package main
+
+import (
+	"context"
+	"github.com/gogf/gf/frame/g"
+	"math"
+	"sparrow/pkg/rpcs"
+	"sparrow/pkg/server"
+	"sparrow/services/emqx-agent/client"
+	"sync"
+	"time"
+
+	"google.golang.org/grpc"
+	pb "sparrow/services/emqx-agent/protobuf"
+)
+
+type Counter struct {
+	count    int64
+	start    int64
+	duration int64
+	maxCount int64
+	lock     sync.Mutex
+}
+
+func NewCounter(duration int64, maxCount int64) *Counter {
+	counter := &Counter{}
+	counter.count = 0
+	counter.start = time.Now().UnixNano() / 1e6 // 当前毫秒时间戳
+	if duration == 0 {
+		counter.duration = math.MaxInt64 // duration传0表示没有时间间隔限制,计数器不刷新
+	} else {
+		counter.duration = duration
+	}
+	counter.maxCount = maxCount
+	return counter
+}
+
+// Count 计数器计数
+// n: 计数值
+// refersh: 计数器是否刷新
+// limit: 是否达到计数最大值
+// num: 计数后计数器的值
+func (counter *Counter) Count(n int64) (refresh bool, limit bool, num int64) {
+	now := time.Now().UnixNano() / 1e6
+	counter.lock.Lock()
+	defer counter.lock.Unlock()
+
+	if now-counter.start < counter.duration {
+		counter.count += n
+		num = counter.count
+		limit = num > counter.maxCount
+	} else {
+		// num = counter.count  // 刷新前的最大计数
+		counter.start = now
+		counter.count = 0
+		refresh = true
+	}
+	return
+}
+
+func (counter *Counter) GetCount() (num int64) {
+	counter.lock.Lock()
+	defer counter.lock.Unlock()
+	return counter.count
+}
+
+var cnter *Counter = NewCounter(0, 100)
+
+// emqttServer is used to implement emqx_exhook_v1.s *emqttServer
+type emqttServer struct {
+	pb.UnimplementedHookProviderServer
+}
+
+// HookProviderServer callbacks
+
+func (s *emqttServer) OnProviderLoaded(ctx context.Context, in *pb.ProviderLoadedRequest) (*pb.LoadedResponse, error) {
+	cnter.Count(1)
+	hooks := []*pb.HookSpec{
+		&pb.HookSpec{Name: "client.connect"},
+		&pb.HookSpec{Name: "client.connack"},
+		&pb.HookSpec{Name: "client.connected"},
+		&pb.HookSpec{Name: "client.disconnected"},
+		&pb.HookSpec{Name: "client.authenticate"},
+		&pb.HookSpec{Name: "client.authorize"},
+		&pb.HookSpec{Name: "client.subscribe"},
+		&pb.HookSpec{Name: "client.unsubscribe"},
+		&pb.HookSpec{Name: "session.created"},
+		&pb.HookSpec{Name: "session.subscribed"},
+		&pb.HookSpec{Name: "session.unsubscribed"},
+		&pb.HookSpec{Name: "session.resumed"},
+		&pb.HookSpec{Name: "session.discarded"},
+		&pb.HookSpec{Name: "session.takenover"},
+		&pb.HookSpec{Name: "session.terminated"},
+		&pb.HookSpec{Name: "message.publish"},
+		&pb.HookSpec{Name: "message.delivered"},
+		&pb.HookSpec{Name: "message.acked"},
+		&pb.HookSpec{Name: "message.dropped"},
+	}
+	return &pb.LoadedResponse{Hooks: hooks}, nil
+}
+
+func (s *emqttServer) OnProviderUnloaded(ctx context.Context, in *pb.ProviderUnloadedRequest) (*pb.EmptySuccess, error) {
+	cnter.Count(1)
+	return &pb.EmptySuccess{}, nil
+}
+
+func (s *emqttServer) OnClientConnect(ctx context.Context, in *pb.ClientConnectRequest) (*pb.EmptySuccess, error) {
+	cnter.Count(1)
+	return &pb.EmptySuccess{}, nil
+}
+
+func (s *emqttServer) OnClientConnack(ctx context.Context, in *pb.ClientConnackRequest) (*pb.EmptySuccess, error) {
+	cnter.Count(1)
+	return &pb.EmptySuccess{}, nil
+}
+
+func (s *emqttServer) OnClientConnected(ctx context.Context, in *pb.ClientConnectedRequest) (*pb.EmptySuccess, error) {
+	cnter.Count(1)
+	return &pb.EmptySuccess{}, nil
+}
+
+func (s *emqttServer) OnClientDisconnected(ctx context.Context, in *pb.ClientDisconnectedRequest) (*pb.EmptySuccess, error) {
+	cnter.Count(1)
+	return &pb.EmptySuccess{}, nil
+}
+
+func (s *emqttServer) OnClientAuthenticate(ctx context.Context, in *pb.ClientAuthenticateRequest) (*pb.ValuedResponse, error) {
+	cnter.Count(1)
+	reply := &pb.ValuedResponse{}
+	reply.Type = pb.ValuedResponse_STOP_AND_RETURN
+	reply.Value = &pb.ValuedResponse_BoolResult{BoolResult: true}
+	return reply, nil
+}
+
+func (s *emqttServer) OnClientAuthorize(ctx context.Context, in *pb.ClientAuthorizeRequest) (*pb.ValuedResponse, error) {
+	cnter.Count(1)
+	reply := &pb.ValuedResponse{}
+	reply.Type = pb.ValuedResponse_STOP_AND_RETURN
+	reply.Value = &pb.ValuedResponse_BoolResult{BoolResult: true}
+	return reply, nil
+}
+
+func (s *emqttServer) OnClientSubscribe(ctx context.Context, in *pb.ClientSubscribeRequest) (*pb.EmptySuccess, error) {
+	cnter.Count(1)
+	return &pb.EmptySuccess{}, nil
+}
+
+func (s *emqttServer) OnClientUnsubscribe(ctx context.Context, in *pb.ClientUnsubscribeRequest) (*pb.EmptySuccess, error) {
+	cnter.Count(1)
+	return &pb.EmptySuccess{}, nil
+}
+
+func (s *emqttServer) OnSessionCreated(ctx context.Context, in *pb.SessionCreatedRequest) (*pb.EmptySuccess, error) {
+	cnter.Count(1)
+	return &pb.EmptySuccess{}, nil
+}
+func (s *emqttServer) OnSessionSubscribed(ctx context.Context, in *pb.SessionSubscribedRequest) (*pb.EmptySuccess, error) {
+	cnter.Count(1)
+	return &pb.EmptySuccess{}, nil
+}
+
+func (s *emqttServer) OnSessionUnsubscribed(ctx context.Context, in *pb.SessionUnsubscribedRequest) (*pb.EmptySuccess, error) {
+	cnter.Count(1)
+	return &pb.EmptySuccess{}, nil
+}
+
+func (s *emqttServer) OnSessionResumed(ctx context.Context, in *pb.SessionResumedRequest) (*pb.EmptySuccess, error) {
+	cnter.Count(1)
+	return &pb.EmptySuccess{}, nil
+}
+
+func (s *emqttServer) OnSessionDiscarded(ctx context.Context, in *pb.SessionDiscardedRequest) (*pb.EmptySuccess, error) {
+	cnter.Count(1)
+	return &pb.EmptySuccess{}, nil
+}
+
+func (s *emqttServer) OnSessionTakenover(ctx context.Context, in *pb.SessionTakenoverRequest) (*pb.EmptySuccess, error) {
+	cnter.Count(1)
+	return &pb.EmptySuccess{}, nil
+}
+
+func (s *emqttServer) OnSessionTerminated(ctx context.Context, in *pb.SessionTerminatedRequest) (*pb.EmptySuccess, error) {
+	cnter.Count(1)
+	return &pb.EmptySuccess{}, nil
+}
+
+func (s *emqttServer) OnMessagePublish(ctx context.Context, in *pb.MessagePublishRequest) (*pb.ValuedResponse, error) {
+	cnter.Count(1)
+	in.Message.Payload = []byte("hardcode payload by exhook-svr-go :)")
+	reply := &pb.ValuedResponse{}
+	reply.Type = pb.ValuedResponse_STOP_AND_RETURN
+	reply.Value = &pb.ValuedResponse_Message{Message: in.Message}
+	return reply, nil
+}
+
+//case2: stop publish the `t/d` messages
+//func (s *emqttServer) OnMessagePublish(ctx context.Context, in *pb.MessagePublishRequest) (*pb.ValuedResponse, error) {
+//	cnter.Count(1)
+//    if in.Message.Topic == "t/d" {
+//        in.Message.Headers["allow_publish"] = "false"
+//        in.Message.Payload = []byte("")
+//    }
+//	reply := &pb.ValuedResponse{}
+//	reply.Type = pb.ValuedResponse_STOP_AND_RETURN
+//	reply.Value = &pb.ValuedResponse_Message{Message: in.Message}
+//	return reply, nil
+//}
+
+func (s *emqttServer) OnMessageDelivered(ctx context.Context, in *pb.MessageDeliveredRequest) (*pb.EmptySuccess, error) {
+	cnter.Count(1)
+	return &pb.EmptySuccess{}, nil
+}
+
+func (s *emqttServer) OnMessageDropped(ctx context.Context, in *pb.MessageDroppedRequest) (*pb.EmptySuccess, error) {
+	cnter.Count(1)
+	return &pb.EmptySuccess{}, nil
+}
+
+func (s *emqttServer) OnMessageAcked(ctx context.Context, in *pb.MessageAckedRequest) (*pb.EmptySuccess, error) {
+	cnter.Count(1)
+	return &pb.EmptySuccess{}, nil
+}
+
+func main() {
+
+	// init emqttServer
+	err := server.Init(rpcs.EmqxAgentServiceName)
+	if err != nil {
+		server.Log.Fatal(err)
+		return
+	}
+
+	sd, err := NewSubDev(&client.MqttConfig{
+		ClientId: g.Cfg().GetString("mqtt.client_id"),
+		User:     g.Cfg().GetString("mqtt.user"),
+		Password: g.Cfg().GetString("mqtt.password"),
+		Brokers:  g.Cfg().GetStrings("mqtt.brokers"),
+		ConnNum:  10,
+	})
+	if err != nil {
+		panic(err)
+	}
+	agent := NewAgent(sd)
+	err = sd.SubDevMsg(func(ctx context.Context) DevSubHandle {
+		return agent
+	})
+	if err != nil {
+		panic(err)
+	}
+	s := grpc.NewServer()
+	pb.RegisterHookProviderServer(s, &emqttServer{})
+	err = server.RegisterHTTPHandler(s)
+	if err != nil {
+		server.Log.Errorf("RegisterHTTPHandler Error: %s", err)
+		return
+	}
+	err = server.RegisterRPCHandler(agent)
+
+	// start to run
+	err = server.Run()
+	if err != nil {
+		server.Log.Fatal(err)
+	}
+}

+ 3455 - 0
services/emqx-agent/protobuf/exhook.pb.go

@@ -0,0 +1,3455 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2020-2022 EMQ Technologies Co., Ltd. All Rights Reserved.
+//
+// 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.
+//------------------------------------------------------------------------------
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.32.0
+// 	protoc        v4.25.1
+// source: protobuf/exhook.proto
+
+// The exhook proto version should be fixed as `v2` in EMQX v5.x
+// to make sure the exhook proto version is compatible
+
+package exhook
+
+import (
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
+)
+
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type ClientAuthorizeRequest_AuthorizeReqType int32
+
+const (
+	ClientAuthorizeRequest_PUBLISH   ClientAuthorizeRequest_AuthorizeReqType = 0
+	ClientAuthorizeRequest_SUBSCRIBE ClientAuthorizeRequest_AuthorizeReqType = 1
+)
+
+// Enum value maps for ClientAuthorizeRequest_AuthorizeReqType.
+var (
+	ClientAuthorizeRequest_AuthorizeReqType_name = map[int32]string{
+		0: "PUBLISH",
+		1: "SUBSCRIBE",
+	}
+	ClientAuthorizeRequest_AuthorizeReqType_value = map[string]int32{
+		"PUBLISH":   0,
+		"SUBSCRIBE": 1,
+	}
+)
+
+func (x ClientAuthorizeRequest_AuthorizeReqType) Enum() *ClientAuthorizeRequest_AuthorizeReqType {
+	p := new(ClientAuthorizeRequest_AuthorizeReqType)
+	*p = x
+	return p
+}
+
+func (x ClientAuthorizeRequest_AuthorizeReqType) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (ClientAuthorizeRequest_AuthorizeReqType) Descriptor() protoreflect.EnumDescriptor {
+	return file_protobuf_exhook_proto_enumTypes[0].Descriptor()
+}
+
+func (ClientAuthorizeRequest_AuthorizeReqType) Type() protoreflect.EnumType {
+	return &file_protobuf_exhook_proto_enumTypes[0]
+}
+
+func (x ClientAuthorizeRequest_AuthorizeReqType) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use ClientAuthorizeRequest_AuthorizeReqType.Descriptor instead.
+func (ClientAuthorizeRequest_AuthorizeReqType) EnumDescriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{7, 0}
+}
+
+// The responded value type
+//  - contiune: Use the responded value and execute the next hook
+//  - ignore: Ignore the responded value
+//  - stop_and_return: Use the responded value and stop the chain executing
+type ValuedResponse_ResponsedType int32
+
+const (
+	ValuedResponse_CONTINUE        ValuedResponse_ResponsedType = 0
+	ValuedResponse_IGNORE          ValuedResponse_ResponsedType = 1
+	ValuedResponse_STOP_AND_RETURN ValuedResponse_ResponsedType = 2
+)
+
+// Enum value maps for ValuedResponse_ResponsedType.
+var (
+	ValuedResponse_ResponsedType_name = map[int32]string{
+		0: "CONTINUE",
+		1: "IGNORE",
+		2: "STOP_AND_RETURN",
+	}
+	ValuedResponse_ResponsedType_value = map[string]int32{
+		"CONTINUE":        0,
+		"IGNORE":          1,
+		"STOP_AND_RETURN": 2,
+	}
+)
+
+func (x ValuedResponse_ResponsedType) Enum() *ValuedResponse_ResponsedType {
+	p := new(ValuedResponse_ResponsedType)
+	*p = x
+	return p
+}
+
+func (x ValuedResponse_ResponsedType) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (ValuedResponse_ResponsedType) Descriptor() protoreflect.EnumDescriptor {
+	return file_protobuf_exhook_proto_enumTypes[1].Descriptor()
+}
+
+func (ValuedResponse_ResponsedType) Type() protoreflect.EnumType {
+	return &file_protobuf_exhook_proto_enumTypes[1]
+}
+
+func (x ValuedResponse_ResponsedType) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use ValuedResponse_ResponsedType.Descriptor instead.
+func (ValuedResponse_ResponsedType) EnumDescriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{22, 0}
+}
+
+type ProviderLoadedRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Broker *BrokerInfo  `protobuf:"bytes,1,opt,name=broker,proto3" json:"broker,omitempty"`
+	Meta   *RequestMeta `protobuf:"bytes,2,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *ProviderLoadedRequest) Reset() {
+	*x = ProviderLoadedRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ProviderLoadedRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ProviderLoadedRequest) ProtoMessage() {}
+
+func (x *ProviderLoadedRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ProviderLoadedRequest.ProtoReflect.Descriptor instead.
+func (*ProviderLoadedRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *ProviderLoadedRequest) GetBroker() *BrokerInfo {
+	if x != nil {
+		return x.Broker
+	}
+	return nil
+}
+
+func (x *ProviderLoadedRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type ProviderUnloadedRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *ProviderUnloadedRequest) Reset() {
+	*x = ProviderUnloadedRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ProviderUnloadedRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ProviderUnloadedRequest) ProtoMessage() {}
+
+func (x *ProviderUnloadedRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[1]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ProviderUnloadedRequest.ProtoReflect.Descriptor instead.
+func (*ProviderUnloadedRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *ProviderUnloadedRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type ClientConnectRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Conninfo *ConnInfo `protobuf:"bytes,1,opt,name=conninfo,proto3" json:"conninfo,omitempty"`
+	// MQTT CONNECT packet's properties (MQTT v5.0)
+	//
+	// It should be empty on MQTT v3.1.1/v3.1 or others protocol
+	Props []*Property  `protobuf:"bytes,2,rep,name=props,proto3" json:"props,omitempty"`
+	Meta  *RequestMeta `protobuf:"bytes,3,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *ClientConnectRequest) Reset() {
+	*x = ClientConnectRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[2]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ClientConnectRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientConnectRequest) ProtoMessage() {}
+
+func (x *ClientConnectRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[2]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ClientConnectRequest.ProtoReflect.Descriptor instead.
+func (*ClientConnectRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *ClientConnectRequest) GetConninfo() *ConnInfo {
+	if x != nil {
+		return x.Conninfo
+	}
+	return nil
+}
+
+func (x *ClientConnectRequest) GetProps() []*Property {
+	if x != nil {
+		return x.Props
+	}
+	return nil
+}
+
+func (x *ClientConnectRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type ClientConnackRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Conninfo   *ConnInfo    `protobuf:"bytes,1,opt,name=conninfo,proto3" json:"conninfo,omitempty"`
+	ResultCode string       `protobuf:"bytes,2,opt,name=result_code,json=resultCode,proto3" json:"result_code,omitempty"`
+	Props      []*Property  `protobuf:"bytes,3,rep,name=props,proto3" json:"props,omitempty"`
+	Meta       *RequestMeta `protobuf:"bytes,4,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *ClientConnackRequest) Reset() {
+	*x = ClientConnackRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[3]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ClientConnackRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientConnackRequest) ProtoMessage() {}
+
+func (x *ClientConnackRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[3]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ClientConnackRequest.ProtoReflect.Descriptor instead.
+func (*ClientConnackRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *ClientConnackRequest) GetConninfo() *ConnInfo {
+	if x != nil {
+		return x.Conninfo
+	}
+	return nil
+}
+
+func (x *ClientConnackRequest) GetResultCode() string {
+	if x != nil {
+		return x.ResultCode
+	}
+	return ""
+}
+
+func (x *ClientConnackRequest) GetProps() []*Property {
+	if x != nil {
+		return x.Props
+	}
+	return nil
+}
+
+func (x *ClientConnackRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type ClientConnectedRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Clientinfo *ClientInfo  `protobuf:"bytes,1,opt,name=clientinfo,proto3" json:"clientinfo,omitempty"`
+	Meta       *RequestMeta `protobuf:"bytes,2,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *ClientConnectedRequest) Reset() {
+	*x = ClientConnectedRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[4]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ClientConnectedRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientConnectedRequest) ProtoMessage() {}
+
+func (x *ClientConnectedRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[4]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ClientConnectedRequest.ProtoReflect.Descriptor instead.
+func (*ClientConnectedRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *ClientConnectedRequest) GetClientinfo() *ClientInfo {
+	if x != nil {
+		return x.Clientinfo
+	}
+	return nil
+}
+
+func (x *ClientConnectedRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type ClientDisconnectedRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Clientinfo *ClientInfo  `protobuf:"bytes,1,opt,name=clientinfo,proto3" json:"clientinfo,omitempty"`
+	Reason     string       `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"`
+	Meta       *RequestMeta `protobuf:"bytes,3,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *ClientDisconnectedRequest) Reset() {
+	*x = ClientDisconnectedRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[5]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ClientDisconnectedRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientDisconnectedRequest) ProtoMessage() {}
+
+func (x *ClientDisconnectedRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[5]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ClientDisconnectedRequest.ProtoReflect.Descriptor instead.
+func (*ClientDisconnectedRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *ClientDisconnectedRequest) GetClientinfo() *ClientInfo {
+	if x != nil {
+		return x.Clientinfo
+	}
+	return nil
+}
+
+func (x *ClientDisconnectedRequest) GetReason() string {
+	if x != nil {
+		return x.Reason
+	}
+	return ""
+}
+
+func (x *ClientDisconnectedRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type ClientAuthenticateRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Clientinfo *ClientInfo  `protobuf:"bytes,1,opt,name=clientinfo,proto3" json:"clientinfo,omitempty"`
+	Result     bool         `protobuf:"varint,2,opt,name=result,proto3" json:"result,omitempty"`
+	Meta       *RequestMeta `protobuf:"bytes,3,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *ClientAuthenticateRequest) Reset() {
+	*x = ClientAuthenticateRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[6]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ClientAuthenticateRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientAuthenticateRequest) ProtoMessage() {}
+
+func (x *ClientAuthenticateRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[6]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ClientAuthenticateRequest.ProtoReflect.Descriptor instead.
+func (*ClientAuthenticateRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *ClientAuthenticateRequest) GetClientinfo() *ClientInfo {
+	if x != nil {
+		return x.Clientinfo
+	}
+	return nil
+}
+
+func (x *ClientAuthenticateRequest) GetResult() bool {
+	if x != nil {
+		return x.Result
+	}
+	return false
+}
+
+func (x *ClientAuthenticateRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type ClientAuthorizeRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Clientinfo *ClientInfo                             `protobuf:"bytes,1,opt,name=clientinfo,proto3" json:"clientinfo,omitempty"`
+	Type       ClientAuthorizeRequest_AuthorizeReqType `protobuf:"varint,2,opt,name=type,proto3,enum=emqx.exhook.v2.ClientAuthorizeRequest_AuthorizeReqType" json:"type,omitempty"`
+	Topic      string                                  `protobuf:"bytes,3,opt,name=topic,proto3" json:"topic,omitempty"`
+	Result     bool                                    `protobuf:"varint,4,opt,name=result,proto3" json:"result,omitempty"`
+	Meta       *RequestMeta                            `protobuf:"bytes,5,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *ClientAuthorizeRequest) Reset() {
+	*x = ClientAuthorizeRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[7]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ClientAuthorizeRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientAuthorizeRequest) ProtoMessage() {}
+
+func (x *ClientAuthorizeRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[7]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ClientAuthorizeRequest.ProtoReflect.Descriptor instead.
+func (*ClientAuthorizeRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *ClientAuthorizeRequest) GetClientinfo() *ClientInfo {
+	if x != nil {
+		return x.Clientinfo
+	}
+	return nil
+}
+
+func (x *ClientAuthorizeRequest) GetType() ClientAuthorizeRequest_AuthorizeReqType {
+	if x != nil {
+		return x.Type
+	}
+	return ClientAuthorizeRequest_PUBLISH
+}
+
+func (x *ClientAuthorizeRequest) GetTopic() string {
+	if x != nil {
+		return x.Topic
+	}
+	return ""
+}
+
+func (x *ClientAuthorizeRequest) GetResult() bool {
+	if x != nil {
+		return x.Result
+	}
+	return false
+}
+
+func (x *ClientAuthorizeRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type ClientSubscribeRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Clientinfo   *ClientInfo    `protobuf:"bytes,1,opt,name=clientinfo,proto3" json:"clientinfo,omitempty"`
+	Props        []*Property    `protobuf:"bytes,2,rep,name=props,proto3" json:"props,omitempty"`
+	TopicFilters []*TopicFilter `protobuf:"bytes,3,rep,name=topic_filters,json=topicFilters,proto3" json:"topic_filters,omitempty"`
+	Meta         *RequestMeta   `protobuf:"bytes,4,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *ClientSubscribeRequest) Reset() {
+	*x = ClientSubscribeRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[8]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ClientSubscribeRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientSubscribeRequest) ProtoMessage() {}
+
+func (x *ClientSubscribeRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[8]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ClientSubscribeRequest.ProtoReflect.Descriptor instead.
+func (*ClientSubscribeRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{8}
+}
+
+func (x *ClientSubscribeRequest) GetClientinfo() *ClientInfo {
+	if x != nil {
+		return x.Clientinfo
+	}
+	return nil
+}
+
+func (x *ClientSubscribeRequest) GetProps() []*Property {
+	if x != nil {
+		return x.Props
+	}
+	return nil
+}
+
+func (x *ClientSubscribeRequest) GetTopicFilters() []*TopicFilter {
+	if x != nil {
+		return x.TopicFilters
+	}
+	return nil
+}
+
+func (x *ClientSubscribeRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type ClientUnsubscribeRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Clientinfo   *ClientInfo    `protobuf:"bytes,1,opt,name=clientinfo,proto3" json:"clientinfo,omitempty"`
+	Props        []*Property    `protobuf:"bytes,2,rep,name=props,proto3" json:"props,omitempty"`
+	TopicFilters []*TopicFilter `protobuf:"bytes,3,rep,name=topic_filters,json=topicFilters,proto3" json:"topic_filters,omitempty"`
+	Meta         *RequestMeta   `protobuf:"bytes,4,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *ClientUnsubscribeRequest) Reset() {
+	*x = ClientUnsubscribeRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[9]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ClientUnsubscribeRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientUnsubscribeRequest) ProtoMessage() {}
+
+func (x *ClientUnsubscribeRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[9]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ClientUnsubscribeRequest.ProtoReflect.Descriptor instead.
+func (*ClientUnsubscribeRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *ClientUnsubscribeRequest) GetClientinfo() *ClientInfo {
+	if x != nil {
+		return x.Clientinfo
+	}
+	return nil
+}
+
+func (x *ClientUnsubscribeRequest) GetProps() []*Property {
+	if x != nil {
+		return x.Props
+	}
+	return nil
+}
+
+func (x *ClientUnsubscribeRequest) GetTopicFilters() []*TopicFilter {
+	if x != nil {
+		return x.TopicFilters
+	}
+	return nil
+}
+
+func (x *ClientUnsubscribeRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type SessionCreatedRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Clientinfo *ClientInfo  `protobuf:"bytes,1,opt,name=clientinfo,proto3" json:"clientinfo,omitempty"`
+	Meta       *RequestMeta `protobuf:"bytes,2,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *SessionCreatedRequest) Reset() {
+	*x = SessionCreatedRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[10]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *SessionCreatedRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SessionCreatedRequest) ProtoMessage() {}
+
+func (x *SessionCreatedRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[10]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use SessionCreatedRequest.ProtoReflect.Descriptor instead.
+func (*SessionCreatedRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *SessionCreatedRequest) GetClientinfo() *ClientInfo {
+	if x != nil {
+		return x.Clientinfo
+	}
+	return nil
+}
+
+func (x *SessionCreatedRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type SessionSubscribedRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Clientinfo *ClientInfo  `protobuf:"bytes,1,opt,name=clientinfo,proto3" json:"clientinfo,omitempty"`
+	Topic      string       `protobuf:"bytes,2,opt,name=topic,proto3" json:"topic,omitempty"`
+	Subopts    *SubOpts     `protobuf:"bytes,3,opt,name=subopts,proto3" json:"subopts,omitempty"`
+	Meta       *RequestMeta `protobuf:"bytes,4,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *SessionSubscribedRequest) Reset() {
+	*x = SessionSubscribedRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[11]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *SessionSubscribedRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SessionSubscribedRequest) ProtoMessage() {}
+
+func (x *SessionSubscribedRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[11]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use SessionSubscribedRequest.ProtoReflect.Descriptor instead.
+func (*SessionSubscribedRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{11}
+}
+
+func (x *SessionSubscribedRequest) GetClientinfo() *ClientInfo {
+	if x != nil {
+		return x.Clientinfo
+	}
+	return nil
+}
+
+func (x *SessionSubscribedRequest) GetTopic() string {
+	if x != nil {
+		return x.Topic
+	}
+	return ""
+}
+
+func (x *SessionSubscribedRequest) GetSubopts() *SubOpts {
+	if x != nil {
+		return x.Subopts
+	}
+	return nil
+}
+
+func (x *SessionSubscribedRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type SessionUnsubscribedRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Clientinfo *ClientInfo  `protobuf:"bytes,1,opt,name=clientinfo,proto3" json:"clientinfo,omitempty"`
+	Topic      string       `protobuf:"bytes,2,opt,name=topic,proto3" json:"topic,omitempty"`
+	Meta       *RequestMeta `protobuf:"bytes,3,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *SessionUnsubscribedRequest) Reset() {
+	*x = SessionUnsubscribedRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[12]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *SessionUnsubscribedRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SessionUnsubscribedRequest) ProtoMessage() {}
+
+func (x *SessionUnsubscribedRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[12]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use SessionUnsubscribedRequest.ProtoReflect.Descriptor instead.
+func (*SessionUnsubscribedRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{12}
+}
+
+func (x *SessionUnsubscribedRequest) GetClientinfo() *ClientInfo {
+	if x != nil {
+		return x.Clientinfo
+	}
+	return nil
+}
+
+func (x *SessionUnsubscribedRequest) GetTopic() string {
+	if x != nil {
+		return x.Topic
+	}
+	return ""
+}
+
+func (x *SessionUnsubscribedRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type SessionResumedRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Clientinfo *ClientInfo  `protobuf:"bytes,1,opt,name=clientinfo,proto3" json:"clientinfo,omitempty"`
+	Meta       *RequestMeta `protobuf:"bytes,2,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *SessionResumedRequest) Reset() {
+	*x = SessionResumedRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[13]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *SessionResumedRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SessionResumedRequest) ProtoMessage() {}
+
+func (x *SessionResumedRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[13]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use SessionResumedRequest.ProtoReflect.Descriptor instead.
+func (*SessionResumedRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{13}
+}
+
+func (x *SessionResumedRequest) GetClientinfo() *ClientInfo {
+	if x != nil {
+		return x.Clientinfo
+	}
+	return nil
+}
+
+func (x *SessionResumedRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type SessionDiscardedRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Clientinfo *ClientInfo  `protobuf:"bytes,1,opt,name=clientinfo,proto3" json:"clientinfo,omitempty"`
+	Meta       *RequestMeta `protobuf:"bytes,2,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *SessionDiscardedRequest) Reset() {
+	*x = SessionDiscardedRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[14]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *SessionDiscardedRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SessionDiscardedRequest) ProtoMessage() {}
+
+func (x *SessionDiscardedRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[14]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use SessionDiscardedRequest.ProtoReflect.Descriptor instead.
+func (*SessionDiscardedRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{14}
+}
+
+func (x *SessionDiscardedRequest) GetClientinfo() *ClientInfo {
+	if x != nil {
+		return x.Clientinfo
+	}
+	return nil
+}
+
+func (x *SessionDiscardedRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type SessionTakenoverRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Clientinfo *ClientInfo  `protobuf:"bytes,1,opt,name=clientinfo,proto3" json:"clientinfo,omitempty"`
+	Meta       *RequestMeta `protobuf:"bytes,2,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *SessionTakenoverRequest) Reset() {
+	*x = SessionTakenoverRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[15]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *SessionTakenoverRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SessionTakenoverRequest) ProtoMessage() {}
+
+func (x *SessionTakenoverRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[15]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use SessionTakenoverRequest.ProtoReflect.Descriptor instead.
+func (*SessionTakenoverRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{15}
+}
+
+func (x *SessionTakenoverRequest) GetClientinfo() *ClientInfo {
+	if x != nil {
+		return x.Clientinfo
+	}
+	return nil
+}
+
+func (x *SessionTakenoverRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type SessionTerminatedRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Clientinfo *ClientInfo  `protobuf:"bytes,1,opt,name=clientinfo,proto3" json:"clientinfo,omitempty"`
+	Reason     string       `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"`
+	Meta       *RequestMeta `protobuf:"bytes,3,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *SessionTerminatedRequest) Reset() {
+	*x = SessionTerminatedRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[16]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *SessionTerminatedRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SessionTerminatedRequest) ProtoMessage() {}
+
+func (x *SessionTerminatedRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[16]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use SessionTerminatedRequest.ProtoReflect.Descriptor instead.
+func (*SessionTerminatedRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{16}
+}
+
+func (x *SessionTerminatedRequest) GetClientinfo() *ClientInfo {
+	if x != nil {
+		return x.Clientinfo
+	}
+	return nil
+}
+
+func (x *SessionTerminatedRequest) GetReason() string {
+	if x != nil {
+		return x.Reason
+	}
+	return ""
+}
+
+func (x *SessionTerminatedRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type MessagePublishRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Message *Message     `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
+	Meta    *RequestMeta `protobuf:"bytes,2,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *MessagePublishRequest) Reset() {
+	*x = MessagePublishRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[17]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *MessagePublishRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*MessagePublishRequest) ProtoMessage() {}
+
+func (x *MessagePublishRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[17]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use MessagePublishRequest.ProtoReflect.Descriptor instead.
+func (*MessagePublishRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{17}
+}
+
+func (x *MessagePublishRequest) GetMessage() *Message {
+	if x != nil {
+		return x.Message
+	}
+	return nil
+}
+
+func (x *MessagePublishRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type MessageDeliveredRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Clientinfo *ClientInfo  `protobuf:"bytes,1,opt,name=clientinfo,proto3" json:"clientinfo,omitempty"`
+	Message    *Message     `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
+	Meta       *RequestMeta `protobuf:"bytes,3,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *MessageDeliveredRequest) Reset() {
+	*x = MessageDeliveredRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[18]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *MessageDeliveredRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*MessageDeliveredRequest) ProtoMessage() {}
+
+func (x *MessageDeliveredRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[18]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use MessageDeliveredRequest.ProtoReflect.Descriptor instead.
+func (*MessageDeliveredRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{18}
+}
+
+func (x *MessageDeliveredRequest) GetClientinfo() *ClientInfo {
+	if x != nil {
+		return x.Clientinfo
+	}
+	return nil
+}
+
+func (x *MessageDeliveredRequest) GetMessage() *Message {
+	if x != nil {
+		return x.Message
+	}
+	return nil
+}
+
+func (x *MessageDeliveredRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type MessageDroppedRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Message *Message     `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
+	Reason  string       `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"`
+	Meta    *RequestMeta `protobuf:"bytes,3,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *MessageDroppedRequest) Reset() {
+	*x = MessageDroppedRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[19]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *MessageDroppedRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*MessageDroppedRequest) ProtoMessage() {}
+
+func (x *MessageDroppedRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[19]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use MessageDroppedRequest.ProtoReflect.Descriptor instead.
+func (*MessageDroppedRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{19}
+}
+
+func (x *MessageDroppedRequest) GetMessage() *Message {
+	if x != nil {
+		return x.Message
+	}
+	return nil
+}
+
+func (x *MessageDroppedRequest) GetReason() string {
+	if x != nil {
+		return x.Reason
+	}
+	return ""
+}
+
+func (x *MessageDroppedRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type MessageAckedRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Clientinfo *ClientInfo  `protobuf:"bytes,1,opt,name=clientinfo,proto3" json:"clientinfo,omitempty"`
+	Message    *Message     `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
+	Meta       *RequestMeta `protobuf:"bytes,3,opt,name=meta,proto3" json:"meta,omitempty"`
+}
+
+func (x *MessageAckedRequest) Reset() {
+	*x = MessageAckedRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[20]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *MessageAckedRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*MessageAckedRequest) ProtoMessage() {}
+
+func (x *MessageAckedRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[20]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use MessageAckedRequest.ProtoReflect.Descriptor instead.
+func (*MessageAckedRequest) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{20}
+}
+
+func (x *MessageAckedRequest) GetClientinfo() *ClientInfo {
+	if x != nil {
+		return x.Clientinfo
+	}
+	return nil
+}
+
+func (x *MessageAckedRequest) GetMessage() *Message {
+	if x != nil {
+		return x.Message
+	}
+	return nil
+}
+
+func (x *MessageAckedRequest) GetMeta() *RequestMeta {
+	if x != nil {
+		return x.Meta
+	}
+	return nil
+}
+
+type LoadedResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Hooks []*HookSpec `protobuf:"bytes,1,rep,name=hooks,proto3" json:"hooks,omitempty"`
+}
+
+func (x *LoadedResponse) Reset() {
+	*x = LoadedResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[21]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *LoadedResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*LoadedResponse) ProtoMessage() {}
+
+func (x *LoadedResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[21]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use LoadedResponse.ProtoReflect.Descriptor instead.
+func (*LoadedResponse) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{21}
+}
+
+func (x *LoadedResponse) GetHooks() []*HookSpec {
+	if x != nil {
+		return x.Hooks
+	}
+	return nil
+}
+
+type ValuedResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Type ValuedResponse_ResponsedType `protobuf:"varint,1,opt,name=type,proto3,enum=emqx.exhook.v2.ValuedResponse_ResponsedType" json:"type,omitempty"`
+	// Types that are assignable to Value:
+	//	*ValuedResponse_BoolResult
+	//	*ValuedResponse_Message
+	Value isValuedResponse_Value `protobuf_oneof:"value"`
+}
+
+func (x *ValuedResponse) Reset() {
+	*x = ValuedResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[22]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ValuedResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ValuedResponse) ProtoMessage() {}
+
+func (x *ValuedResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[22]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ValuedResponse.ProtoReflect.Descriptor instead.
+func (*ValuedResponse) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{22}
+}
+
+func (x *ValuedResponse) GetType() ValuedResponse_ResponsedType {
+	if x != nil {
+		return x.Type
+	}
+	return ValuedResponse_CONTINUE
+}
+
+func (m *ValuedResponse) GetValue() isValuedResponse_Value {
+	if m != nil {
+		return m.Value
+	}
+	return nil
+}
+
+func (x *ValuedResponse) GetBoolResult() bool {
+	if x, ok := x.GetValue().(*ValuedResponse_BoolResult); ok {
+		return x.BoolResult
+	}
+	return false
+}
+
+func (x *ValuedResponse) GetMessage() *Message {
+	if x, ok := x.GetValue().(*ValuedResponse_Message); ok {
+		return x.Message
+	}
+	return nil
+}
+
+type isValuedResponse_Value interface {
+	isValuedResponse_Value()
+}
+
+type ValuedResponse_BoolResult struct {
+	// Boolean result, used on the 'client.authenticate', 'client.authorize' hooks
+	BoolResult bool `protobuf:"varint,3,opt,name=bool_result,json=boolResult,proto3,oneof"`
+}
+
+type ValuedResponse_Message struct {
+	// Message result, used on the 'message.*' hooks
+	Message *Message `protobuf:"bytes,4,opt,name=message,proto3,oneof"`
+}
+
+func (*ValuedResponse_BoolResult) isValuedResponse_Value() {}
+
+func (*ValuedResponse_Message) isValuedResponse_Value() {}
+
+type EmptySuccess struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+}
+
+func (x *EmptySuccess) Reset() {
+	*x = EmptySuccess{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[23]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *EmptySuccess) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EmptySuccess) ProtoMessage() {}
+
+func (x *EmptySuccess) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[23]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use EmptySuccess.ProtoReflect.Descriptor instead.
+func (*EmptySuccess) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{23}
+}
+
+type BrokerInfo struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Version  string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"`
+	Sysdescr string `protobuf:"bytes,2,opt,name=sysdescr,proto3" json:"sysdescr,omitempty"`
+	Uptime   int64  `protobuf:"varint,3,opt,name=uptime,proto3" json:"uptime,omitempty"`
+	Datetime string `protobuf:"bytes,4,opt,name=datetime,proto3" json:"datetime,omitempty"`
+}
+
+func (x *BrokerInfo) Reset() {
+	*x = BrokerInfo{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[24]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *BrokerInfo) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*BrokerInfo) ProtoMessage() {}
+
+func (x *BrokerInfo) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[24]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use BrokerInfo.ProtoReflect.Descriptor instead.
+func (*BrokerInfo) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{24}
+}
+
+func (x *BrokerInfo) GetVersion() string {
+	if x != nil {
+		return x.Version
+	}
+	return ""
+}
+
+func (x *BrokerInfo) GetSysdescr() string {
+	if x != nil {
+		return x.Sysdescr
+	}
+	return ""
+}
+
+func (x *BrokerInfo) GetUptime() int64 {
+	if x != nil {
+		return x.Uptime
+	}
+	return 0
+}
+
+func (x *BrokerInfo) GetDatetime() string {
+	if x != nil {
+		return x.Datetime
+	}
+	return ""
+}
+
+type HookSpec struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	// The registered hooks name
+	//
+	// Available value:
+	//   "client.connect",      "client.connack"
+	//   "client.connected",    "client.disconnected"
+	//   "client.authenticate", "client.authorize"
+	//   "client.subscribe",    "client.unsubscribe"
+	//
+	//   "session.created",      "session.subscribed"
+	//   "session.unsubscribed", "session.resumed"
+	//   "session.discarded",    "session.takenover"
+	//   "session.terminated"
+	//
+	//   "message.publish", "message.delivered"
+	//   "message.acked",   "message.dropped"
+	Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+	// The topic filters for message hooks
+	Topics []string `protobuf:"bytes,2,rep,name=topics,proto3" json:"topics,omitempty"`
+}
+
+func (x *HookSpec) Reset() {
+	*x = HookSpec{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[25]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *HookSpec) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HookSpec) ProtoMessage() {}
+
+func (x *HookSpec) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[25]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use HookSpec.ProtoReflect.Descriptor instead.
+func (*HookSpec) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{25}
+}
+
+func (x *HookSpec) GetName() string {
+	if x != nil {
+		return x.Name
+	}
+	return ""
+}
+
+func (x *HookSpec) GetTopics() []string {
+	if x != nil {
+		return x.Topics
+	}
+	return nil
+}
+
+type ConnInfo struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Node      string `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
+	Clientid  string `protobuf:"bytes,2,opt,name=clientid,proto3" json:"clientid,omitempty"`
+	Username  string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"`
+	Peerhost  string `protobuf:"bytes,4,opt,name=peerhost,proto3" json:"peerhost,omitempty"`
+	Sockport  uint32 `protobuf:"varint,5,opt,name=sockport,proto3" json:"sockport,omitempty"`
+	ProtoName string `protobuf:"bytes,6,opt,name=proto_name,json=protoName,proto3" json:"proto_name,omitempty"`
+	ProtoVer  string `protobuf:"bytes,7,opt,name=proto_ver,json=protoVer,proto3" json:"proto_ver,omitempty"`
+	Keepalive uint32 `protobuf:"varint,8,opt,name=keepalive,proto3" json:"keepalive,omitempty"`
+}
+
+func (x *ConnInfo) Reset() {
+	*x = ConnInfo{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[26]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ConnInfo) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ConnInfo) ProtoMessage() {}
+
+func (x *ConnInfo) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[26]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ConnInfo.ProtoReflect.Descriptor instead.
+func (*ConnInfo) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{26}
+}
+
+func (x *ConnInfo) GetNode() string {
+	if x != nil {
+		return x.Node
+	}
+	return ""
+}
+
+func (x *ConnInfo) GetClientid() string {
+	if x != nil {
+		return x.Clientid
+	}
+	return ""
+}
+
+func (x *ConnInfo) GetUsername() string {
+	if x != nil {
+		return x.Username
+	}
+	return ""
+}
+
+func (x *ConnInfo) GetPeerhost() string {
+	if x != nil {
+		return x.Peerhost
+	}
+	return ""
+}
+
+func (x *ConnInfo) GetSockport() uint32 {
+	if x != nil {
+		return x.Sockport
+	}
+	return 0
+}
+
+func (x *ConnInfo) GetProtoName() string {
+	if x != nil {
+		return x.ProtoName
+	}
+	return ""
+}
+
+func (x *ConnInfo) GetProtoVer() string {
+	if x != nil {
+		return x.ProtoVer
+	}
+	return ""
+}
+
+func (x *ConnInfo) GetKeepalive() uint32 {
+	if x != nil {
+		return x.Keepalive
+	}
+	return 0
+}
+
+type ClientInfo struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Node        string `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
+	Clientid    string `protobuf:"bytes,2,opt,name=clientid,proto3" json:"clientid,omitempty"`
+	Username    string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"`
+	Password    string `protobuf:"bytes,4,opt,name=password,proto3" json:"password,omitempty"`
+	Peerhost    string `protobuf:"bytes,5,opt,name=peerhost,proto3" json:"peerhost,omitempty"`
+	Sockport    uint32 `protobuf:"varint,6,opt,name=sockport,proto3" json:"sockport,omitempty"`
+	Protocol    string `protobuf:"bytes,7,opt,name=protocol,proto3" json:"protocol,omitempty"`
+	Mountpoint  string `protobuf:"bytes,8,opt,name=mountpoint,proto3" json:"mountpoint,omitempty"`
+	IsSuperuser bool   `protobuf:"varint,9,opt,name=is_superuser,json=isSuperuser,proto3" json:"is_superuser,omitempty"`
+	Anonymous   bool   `protobuf:"varint,10,opt,name=anonymous,proto3" json:"anonymous,omitempty"`
+	// common name of client TLS cert
+	Cn string `protobuf:"bytes,11,opt,name=cn,proto3" json:"cn,omitempty"`
+	// subject of client TLS cert
+	Dn string `protobuf:"bytes,12,opt,name=dn,proto3" json:"dn,omitempty"`
+}
+
+func (x *ClientInfo) Reset() {
+	*x = ClientInfo{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[27]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ClientInfo) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClientInfo) ProtoMessage() {}
+
+func (x *ClientInfo) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[27]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ClientInfo.ProtoReflect.Descriptor instead.
+func (*ClientInfo) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{27}
+}
+
+func (x *ClientInfo) GetNode() string {
+	if x != nil {
+		return x.Node
+	}
+	return ""
+}
+
+func (x *ClientInfo) GetClientid() string {
+	if x != nil {
+		return x.Clientid
+	}
+	return ""
+}
+
+func (x *ClientInfo) GetUsername() string {
+	if x != nil {
+		return x.Username
+	}
+	return ""
+}
+
+func (x *ClientInfo) GetPassword() string {
+	if x != nil {
+		return x.Password
+	}
+	return ""
+}
+
+func (x *ClientInfo) GetPeerhost() string {
+	if x != nil {
+		return x.Peerhost
+	}
+	return ""
+}
+
+func (x *ClientInfo) GetSockport() uint32 {
+	if x != nil {
+		return x.Sockport
+	}
+	return 0
+}
+
+func (x *ClientInfo) GetProtocol() string {
+	if x != nil {
+		return x.Protocol
+	}
+	return ""
+}
+
+func (x *ClientInfo) GetMountpoint() string {
+	if x != nil {
+		return x.Mountpoint
+	}
+	return ""
+}
+
+func (x *ClientInfo) GetIsSuperuser() bool {
+	if x != nil {
+		return x.IsSuperuser
+	}
+	return false
+}
+
+func (x *ClientInfo) GetAnonymous() bool {
+	if x != nil {
+		return x.Anonymous
+	}
+	return false
+}
+
+func (x *ClientInfo) GetCn() string {
+	if x != nil {
+		return x.Cn
+	}
+	return ""
+}
+
+func (x *ClientInfo) GetDn() string {
+	if x != nil {
+		return x.Dn
+	}
+	return ""
+}
+
+type Message struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Node      string `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
+	Id        string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
+	Qos       uint32 `protobuf:"varint,3,opt,name=qos,proto3" json:"qos,omitempty"`
+	From      string `protobuf:"bytes,4,opt,name=from,proto3" json:"from,omitempty"`
+	Topic     string `protobuf:"bytes,5,opt,name=topic,proto3" json:"topic,omitempty"`
+	Payload   []byte `protobuf:"bytes,6,opt,name=payload,proto3" json:"payload,omitempty"`
+	Timestamp uint64 `protobuf:"varint,7,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	// The key of header can be:
+	//  - username:
+	//    * Readonly
+	//    * The username of sender client
+	//    * Value type: utf8 string
+	//  - protocol:
+	//    * Readonly
+	//    * The protocol name of sender client
+	//    * Value type: string enum with "mqtt", "mqtt-sn", ...
+	//  - peerhost:
+	//    * Readonly
+	//    * The peerhost of sender client
+	//    * Value type: ip address string
+	//  - allow_publish:
+	//    * Writable
+	//    * Whether to allow the message to be published by emqx
+	//    * Value type: string enum with "true", "false", default is "true"
+	//
+	// Notes: All header may be missing, which means that the message does not
+	//   carry these headers. We can guarantee that clients coming from MQTT,
+	//   MQTT-SN, CoAP, LwM2M and other natively supported protocol clients will
+	//   carry these headers, but there is no guarantee that messages published
+	//   by other means will do, e.g. messages published by HTTP-API
+	Headers map[string]string `protobuf:"bytes,8,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+}
+
+func (x *Message) Reset() {
+	*x = Message{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[28]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *Message) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Message) ProtoMessage() {}
+
+func (x *Message) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[28]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use Message.ProtoReflect.Descriptor instead.
+func (*Message) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{28}
+}
+
+func (x *Message) GetNode() string {
+	if x != nil {
+		return x.Node
+	}
+	return ""
+}
+
+func (x *Message) GetId() string {
+	if x != nil {
+		return x.Id
+	}
+	return ""
+}
+
+func (x *Message) GetQos() uint32 {
+	if x != nil {
+		return x.Qos
+	}
+	return 0
+}
+
+func (x *Message) GetFrom() string {
+	if x != nil {
+		return x.From
+	}
+	return ""
+}
+
+func (x *Message) GetTopic() string {
+	if x != nil {
+		return x.Topic
+	}
+	return ""
+}
+
+func (x *Message) GetPayload() []byte {
+	if x != nil {
+		return x.Payload
+	}
+	return nil
+}
+
+func (x *Message) GetTimestamp() uint64 {
+	if x != nil {
+		return x.Timestamp
+	}
+	return 0
+}
+
+func (x *Message) GetHeaders() map[string]string {
+	if x != nil {
+		return x.Headers
+	}
+	return nil
+}
+
+type Property struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Name  string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+	Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (x *Property) Reset() {
+	*x = Property{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[29]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *Property) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Property) ProtoMessage() {}
+
+func (x *Property) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[29]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use Property.ProtoReflect.Descriptor instead.
+func (*Property) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{29}
+}
+
+func (x *Property) GetName() string {
+	if x != nil {
+		return x.Name
+	}
+	return ""
+}
+
+func (x *Property) GetValue() string {
+	if x != nil {
+		return x.Value
+	}
+	return ""
+}
+
+type TopicFilter struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+	Qos  uint32 `protobuf:"varint,2,opt,name=qos,proto3" json:"qos,omitempty"`
+}
+
+func (x *TopicFilter) Reset() {
+	*x = TopicFilter{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[30]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *TopicFilter) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TopicFilter) ProtoMessage() {}
+
+func (x *TopicFilter) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[30]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use TopicFilter.ProtoReflect.Descriptor instead.
+func (*TopicFilter) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{30}
+}
+
+func (x *TopicFilter) GetName() string {
+	if x != nil {
+		return x.Name
+	}
+	return ""
+}
+
+func (x *TopicFilter) GetQos() uint32 {
+	if x != nil {
+		return x.Qos
+	}
+	return 0
+}
+
+type SubOpts struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	// The QoS level
+	Qos uint32 `protobuf:"varint,1,opt,name=qos,proto3" json:"qos,omitempty"`
+	// The group name for shared subscription
+	Share string `protobuf:"bytes,2,opt,name=share,proto3" json:"share,omitempty"`
+	// The Retain Handling option (MQTT v5.0)
+	//
+	//  0 = Send retained messages at the time of the subscribe
+	//  1 = Send retained messages at subscribe only if the subscription does
+	//       not currently exist
+	//  2 = Do not send retained messages at the time of the subscribe
+	Rh uint32 `protobuf:"varint,3,opt,name=rh,proto3" json:"rh,omitempty"`
+	// The Retain as Published option (MQTT v5.0)
+	//
+	//  If 1, Application Messages forwarded using this subscription keep the
+	//        RETAIN flag they were published with.
+	//  If 0, Application Messages forwarded using this subscription have the
+	//        RETAIN flag set to 0.
+	// Retained messages sent when the subscription is established have the RETAIN flag set to 1.
+	Rap uint32 `protobuf:"varint,4,opt,name=rap,proto3" json:"rap,omitempty"`
+	// The No Local option (MQTT v5.0)
+	//
+	// If the value is 1, Application Messages MUST NOT be forwarded to a
+	// connection with a ClientID equal to the ClientID of the publishing
+	Nl uint32 `protobuf:"varint,5,opt,name=nl,proto3" json:"nl,omitempty"`
+}
+
+func (x *SubOpts) Reset() {
+	*x = SubOpts{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[31]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *SubOpts) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SubOpts) ProtoMessage() {}
+
+func (x *SubOpts) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[31]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use SubOpts.ProtoReflect.Descriptor instead.
+func (*SubOpts) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{31}
+}
+
+func (x *SubOpts) GetQos() uint32 {
+	if x != nil {
+		return x.Qos
+	}
+	return 0
+}
+
+func (x *SubOpts) GetShare() string {
+	if x != nil {
+		return x.Share
+	}
+	return ""
+}
+
+func (x *SubOpts) GetRh() uint32 {
+	if x != nil {
+		return x.Rh
+	}
+	return 0
+}
+
+func (x *SubOpts) GetRap() uint32 {
+	if x != nil {
+		return x.Rap
+	}
+	return 0
+}
+
+func (x *SubOpts) GetNl() uint32 {
+	if x != nil {
+		return x.Nl
+	}
+	return 0
+}
+
+type RequestMeta struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Node        string `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
+	Version     string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"`
+	Sysdescr    string `protobuf:"bytes,3,opt,name=sysdescr,proto3" json:"sysdescr,omitempty"`
+	ClusterName string `protobuf:"bytes,4,opt,name=cluster_name,json=clusterName,proto3" json:"cluster_name,omitempty"`
+}
+
+func (x *RequestMeta) Reset() {
+	*x = RequestMeta{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_protobuf_exhook_proto_msgTypes[32]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *RequestMeta) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*RequestMeta) ProtoMessage() {}
+
+func (x *RequestMeta) ProtoReflect() protoreflect.Message {
+	mi := &file_protobuf_exhook_proto_msgTypes[32]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use RequestMeta.ProtoReflect.Descriptor instead.
+func (*RequestMeta) Descriptor() ([]byte, []int) {
+	return file_protobuf_exhook_proto_rawDescGZIP(), []int{32}
+}
+
+func (x *RequestMeta) GetNode() string {
+	if x != nil {
+		return x.Node
+	}
+	return ""
+}
+
+func (x *RequestMeta) GetVersion() string {
+	if x != nil {
+		return x.Version
+	}
+	return ""
+}
+
+func (x *RequestMeta) GetSysdescr() string {
+	if x != nil {
+		return x.Sysdescr
+	}
+	return ""
+}
+
+func (x *RequestMeta) GetClusterName() string {
+	if x != nil {
+		return x.ClusterName
+	}
+	return ""
+}
+
+var File_protobuf_exhook_proto protoreflect.FileDescriptor
+
+var file_protobuf_exhook_proto_rawDesc = []byte{
+	0x0a, 0x15, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x78, 0x68, 0x6f, 0x6f,
+	0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78,
+	0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x22, 0x7c, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x76, 0x69,
+	0x64, 0x65, 0x72, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x12, 0x32, 0x0a, 0x06, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x1a, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76,
+	0x32, 0x2e, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x62, 0x72,
+	0x6f, 0x6b, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b,
+	0x2e, 0x76, 0x32, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52,
+	0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x4a, 0x0a, 0x17, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65,
+	0x72, 0x55, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b,
+	0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74,
+	0x61, 0x22, 0xad, 0x01, 0x0a, 0x14, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e,
+	0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x08, 0x63, 0x6f,
+	0x6e, 0x6e, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65,
+	0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6f,
+	0x6e, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x6e, 0x69, 0x6e, 0x66, 0x6f,
+	0x12, 0x2e, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x70, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
+	0x18, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32,
+	0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x70, 0x73,
+	0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b,
+	0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74,
+	0x61, 0x22, 0xce, 0x01, 0x0a, 0x14, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e,
+	0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x08, 0x63, 0x6f,
+	0x6e, 0x6e, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65,
+	0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6f,
+	0x6e, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x6e, 0x69, 0x6e, 0x66, 0x6f,
+	0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x64,
+	0x65, 0x12, 0x2e, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x70, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
+	0x32, 0x18, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76,
+	0x32, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x70,
+	0x73, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
+	0x1b, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32,
+	0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65,
+	0x74, 0x61, 0x22, 0x85, 0x01, 0x0a, 0x16, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e,
+	0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a,
+	0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e,
+	0x76, 0x32, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63,
+	0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74,
+	0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65,
+	0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0xa0, 0x01, 0x0a, 0x19, 0x43,
+	0x6c, 0x69, 0x65, 0x6e, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65,
+	0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x65,
+	0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65,
+	0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c,
+	0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
+	0x69, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x04,
+	0x6d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x6d, 0x71,
+	0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0xa0, 0x01,
+	0x0a, 0x19, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69,
+	0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x0a, 0x63,
+	0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+	0x1a, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32,
+	0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69,
+	0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c,
+	0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12,
+	0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e,
+	0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61,
+	0x22, 0xb0, 0x02, 0x0a, 0x16, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f,
+	0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x0a, 0x63,
+	0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+	0x1a, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32,
+	0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69,
+	0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x4b, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x37, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68,
+	0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x41, 0x75, 0x74,
+	0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x41, 0x75,
+	0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04,
+	0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x03, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65,
+	0x73, 0x75, 0x6c, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75,
+	0x6c, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x1b, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76,
+	0x32, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d,
+	0x65, 0x74, 0x61, 0x22, 0x2e, 0x0a, 0x10, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65,
+	0x52, 0x65, 0x71, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x55, 0x42, 0x4c, 0x49,
+	0x53, 0x48, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x42,
+	0x45, 0x10, 0x01, 0x22, 0xf7, 0x01, 0x0a, 0x16, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x75,
+	0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a,
+	0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b,
+	0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a,
+	0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x05, 0x70, 0x72,
+	0x6f, 0x70, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65, 0x6d, 0x71, 0x78,
+	0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65,
+	0x72, 0x74, 0x79, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x70, 0x73, 0x12, 0x40, 0x0a, 0x0d, 0x74, 0x6f,
+	0x70, 0x69, 0x63, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
+	0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e,
+	0x76, 0x32, 0x2e, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0c,
+	0x74, 0x6f, 0x70, 0x69, 0x63, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x2f, 0x0a, 0x04,
+	0x6d, 0x65, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x6d, 0x71,
+	0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0xf9, 0x01,
+	0x0a, 0x18, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x6e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72,
+	0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x0a, 0x63, 0x6c,
+	0x69, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
+	0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e,
+	0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65,
+	0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x70, 0x73, 0x18,
+	0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68,
+	0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x52,
+	0x05, 0x70, 0x72, 0x6f, 0x70, 0x73, 0x12, 0x40, 0x0a, 0x0d, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x5f,
+	0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e,
+	0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x54,
+	0x6f, 0x70, 0x69, 0x63, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0c, 0x74, 0x6f, 0x70, 0x69,
+	0x63, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61,
+	0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78,
+	0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d,
+	0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x84, 0x01, 0x0a, 0x15, 0x53, 0x65,
+	0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66,
+	0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65,
+	0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49,
+	0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12,
+	0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e,
+	0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61,
+	0x22, 0xd0, 0x01, 0x0a, 0x18, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x75, 0x62, 0x73,
+	0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a,
+	0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e,
+	0x76, 0x32, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63,
+	0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70,
+	0x69, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12,
+	0x31, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6f, 0x70, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x17, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76,
+	0x32, 0x2e, 0x53, 0x75, 0x62, 0x4f, 0x70, 0x74, 0x73, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6f, 0x70,
+	0x74, 0x73, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x1b, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76,
+	0x32, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d,
+	0x65, 0x74, 0x61, 0x22, 0x9f, 0x01, 0x0a, 0x1a, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x55,
+	0x6e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x12, 0x3a, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78,
+	0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e,
+	0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x14,
+	0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74,
+	0x6f, 0x70, 0x69, 0x63, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b,
+	0x2e, 0x76, 0x32, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52,
+	0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x84, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f,
+	0x6e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
+	0x3a, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f,
+	0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52,
+	0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x2f, 0x0a, 0x04, 0x6d,
+	0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x6d, 0x71, 0x78,
+	0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x86, 0x01, 0x0a,
+	0x17, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x44, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x65,
+	0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x65,
+	0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65,
+	0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c,
+	0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
+	0x69, 0x6e, 0x66, 0x6f, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b,
+	0x2e, 0x76, 0x32, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52,
+	0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x86, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f,
+	0x6e, 0x54, 0x61, 0x6b, 0x65, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x12, 0x3a, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68,
+	0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66,
+	0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x2f, 0x0a,
+	0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x6d,
+	0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x9f,
+	0x01, 0x0a, 0x18, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e,
+	0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x0a, 0x63,
+	0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+	0x1a, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32,
+	0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69,
+	0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f,
+	0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12,
+	0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e,
+	0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61,
+	0x22, 0x7b, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69,
+	0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x07, 0x6d, 0x65, 0x73,
+	0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x65, 0x6d, 0x71,
+	0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x73, 0x73,
+	0x61, 0x67, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2f, 0x0a, 0x04,
+	0x6d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x6d, 0x71,
+	0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0xb9, 0x01,
+	0x0a, 0x17, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72,
+	0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x0a, 0x63, 0x6c, 0x69,
+	0x65, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
+	0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x43,
+	0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e,
+	0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x31, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78,
+	0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52,
+	0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61,
+	0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78,
+	0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d,
+	0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x93, 0x01, 0x0a, 0x15, 0x4d, 0x65,
+	0x73, 0x73, 0x61, 0x67, 0x65, 0x44, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f,
+	0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x07, 0x6d,
+	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x2f,
+	0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65,
+	0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22,
+	0xb5, 0x01, 0x0a, 0x13, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x41, 0x63, 0x6b, 0x65, 0x64,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e,
+	0x74, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x6d,
+	0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x69,
+	0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69,
+	0x6e, 0x66, 0x6f, 0x12, 0x31, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f,
+	0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x07, 0x6d,
+	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x03,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f,
+	0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74,
+	0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x40, 0x0a, 0x0e, 0x4c, 0x6f, 0x61, 0x64, 0x65,
+	0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x68, 0x6f, 0x6f,
+	0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e,
+	0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x48, 0x6f, 0x6f, 0x6b, 0x53, 0x70,
+	0x65, 0x63, 0x52, 0x05, 0x68, 0x6f, 0x6f, 0x6b, 0x73, 0x22, 0xf3, 0x01, 0x0a, 0x0e, 0x56, 0x61,
+	0x6c, 0x75, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x04,
+	0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x65, 0x6d, 0x71,
+	0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x61, 0x6c, 0x75,
+	0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x21,
+	0x0a, 0x0b, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20,
+	0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x75, 0x6c,
+	0x74, 0x12, 0x33, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x17, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b,
+	0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x07, 0x6d,
+	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3e, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x4f, 0x4e, 0x54, 0x49,
+	0x4e, 0x55, 0x45, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x49, 0x47, 0x4e, 0x4f, 0x52, 0x45, 0x10,
+	0x01, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x54, 0x4f, 0x50, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x52, 0x45,
+	0x54, 0x55, 0x52, 0x4e, 0x10, 0x02, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22,
+	0x0e, 0x0a, 0x0c, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22,
+	0x76, 0x0a, 0x0a, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x18, 0x0a,
+	0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
+	0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x79, 0x73, 0x64, 0x65,
+	0x73, 0x63, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x79, 0x73, 0x64, 0x65,
+	0x73, 0x63, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20,
+	0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x64,
+	0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64,
+	0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x36, 0x0a, 0x08, 0x48, 0x6f, 0x6f, 0x6b, 0x53,
+	0x70, 0x65, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x6f, 0x70, 0x69, 0x63,
+	0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x22,
+	0xe8, 0x01, 0x0a, 0x08, 0x43, 0x6f, 0x6e, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04,
+	0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65,
+	0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08,
+	0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
+	0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x65, 0x65, 0x72,
+	0x68, 0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x65, 0x65, 0x72,
+	0x68, 0x6f, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x6f, 0x63, 0x6b, 0x70, 0x6f, 0x72, 0x74,
+	0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x6f, 0x63, 0x6b, 0x70, 0x6f, 0x72, 0x74,
+	0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x4e, 0x61, 0x6d, 0x65, 0x12,
+	0x1b, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5f, 0x76, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x56, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09,
+	0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52,
+	0x09, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x22, 0xc9, 0x02, 0x0a, 0x0a, 0x43,
+	0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x6f, 0x64,
+	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a,
+	0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65,
+	0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65,
+	0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
+	0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
+	0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x65, 0x65, 0x72, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x65, 0x65, 0x72, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x1a, 0x0a,
+	0x08, 0x73, 0x6f, 0x63, 0x6b, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52,
+	0x08, 0x73, 0x6f, 0x63, 0x6b, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x70, 0x6f,
+	0x69, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
+	0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x73, 0x75, 0x70, 0x65,
+	0x72, 0x75, 0x73, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x53,
+	0x75, 0x70, 0x65, 0x72, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x6e, 0x6f, 0x6e,
+	0x79, 0x6d, 0x6f, 0x75, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x6e, 0x6f,
+	0x6e, 0x79, 0x6d, 0x6f, 0x75, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x63, 0x6e, 0x18, 0x0b, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x02, 0x63, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x64, 0x6e, 0x18, 0x0c, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x02, 0x64, 0x6e, 0x22, 0x9d, 0x02, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61,
+	0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x71, 0x6f, 0x73, 0x18, 0x03, 0x20,
+	0x01, 0x28, 0x0d, 0x52, 0x03, 0x71, 0x6f, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d,
+	0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x14, 0x0a, 0x05,
+	0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70,
+	0x69, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x06, 0x20,
+	0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x1c, 0x0a, 0x09,
+	0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52,
+	0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3e, 0x0a, 0x07, 0x68, 0x65,
+	0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x6d,
+	0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x73,
+	0x73, 0x61, 0x67, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72,
+	0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x1a, 0x3a, 0x0a, 0x0c, 0x48, 0x65,
+	0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
+	0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05,
+	0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c,
+	0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x34, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72,
+	0x74, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x33, 0x0a, 0x0b,
+	0x54, 0x6f, 0x70, 0x69, 0x63, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e,
+	0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
+	0x10, 0x0a, 0x03, 0x71, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x71, 0x6f,
+	0x73, 0x22, 0x63, 0x0a, 0x07, 0x53, 0x75, 0x62, 0x4f, 0x70, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03,
+	0x71, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x71, 0x6f, 0x73, 0x12, 0x14,
+	0x0a, 0x05, 0x73, 0x68, 0x61, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73,
+	0x68, 0x61, 0x72, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x72, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d,
+	0x52, 0x02, 0x72, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x61, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28,
+	0x0d, 0x52, 0x03, 0x72, 0x61, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x6e, 0x6c, 0x18, 0x05, 0x20, 0x01,
+	0x28, 0x0d, 0x52, 0x02, 0x6e, 0x6c, 0x22, 0x7a, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72,
+	0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73,
+	0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x79, 0x73, 0x64, 0x65, 0x73, 0x63, 0x72, 0x18,
+	0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x79, 0x73, 0x64, 0x65, 0x73, 0x63, 0x72, 0x12,
+	0x21, 0x0a, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+	0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61,
+	0x6d, 0x65, 0x32, 0xc7, 0x0f, 0x0a, 0x0c, 0x48, 0x6f, 0x6f, 0x6b, 0x50, 0x72, 0x6f, 0x76, 0x69,
+	0x64, 0x65, 0x72, 0x12, 0x5b, 0x0a, 0x10, 0x4f, 0x6e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65,
+	0x72, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x12, 0x25, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65,
+	0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65,
+	0x72, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e,
+	0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e,
+	0x4c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
+	0x12, 0x5d, 0x0a, 0x12, 0x4f, 0x6e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x55, 0x6e,
+	0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x12, 0x27, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78,
+	0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72,
+	0x55, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+	0x1c, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32,
+	0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x00, 0x12,
+	0x57, 0x0a, 0x0f, 0x4f, 0x6e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
+	0x63, 0x74, 0x12, 0x24, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b,
+	0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
+	0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e,
+	0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53,
+	0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x0f, 0x4f, 0x6e, 0x43, 0x6c,
+	0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x61, 0x63, 0x6b, 0x12, 0x24, 0x2e, 0x65, 0x6d,
+	0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x69,
+	0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x1a, 0x1c, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e,
+	0x76, 0x32, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22,
+	0x00, 0x12, 0x5b, 0x0a, 0x11, 0x4f, 0x6e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e,
+	0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x26, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78,
+	0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f,
+	0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c,
+	0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e,
+	0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x00, 0x12, 0x61,
+	0x0a, 0x14, 0x4f, 0x6e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e,
+	0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x29, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78,
+	0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x44, 0x69,
+	0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x1a, 0x1c, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e,
+	0x76, 0x32, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22,
+	0x00, 0x12, 0x63, 0x0a, 0x14, 0x4f, 0x6e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x41, 0x75, 0x74,
+	0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x65, 0x6d, 0x71, 0x78,
+	0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e,
+	0x74, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f,
+	0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5d, 0x0a, 0x11, 0x4f, 0x6e, 0x43, 0x6c, 0x69, 0x65,
+	0x6e, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x12, 0x26, 0x2e, 0x65, 0x6d,
+	0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x69,
+	0x65, 0x6e, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f,
+	0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x11, 0x4f, 0x6e, 0x43, 0x6c, 0x69, 0x65, 0x6e,
+	0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x26, 0x2e, 0x65, 0x6d, 0x71,
+	0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x69, 0x65,
+	0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b,
+	0x2e, 0x76, 0x32, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73,
+	0x22, 0x00, 0x12, 0x5f, 0x0a, 0x13, 0x4f, 0x6e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x6e,
+	0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x28, 0x2e, 0x65, 0x6d, 0x71, 0x78,
+	0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e,
+	0x74, 0x55, 0x6e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f,
+	0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73,
+	0x73, 0x22, 0x00, 0x12, 0x59, 0x0a, 0x10, 0x4f, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
+	0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x25, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65,
+	0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
+	0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c,
+	0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e,
+	0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x00, 0x12, 0x5f,
+	0x0a, 0x13, 0x4f, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x75, 0x62, 0x73, 0x63,
+	0x72, 0x69, 0x62, 0x65, 0x64, 0x12, 0x28, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68,
+	0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x75,
+	0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+	0x1c, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32,
+	0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x00, 0x12,
+	0x63, 0x0a, 0x15, 0x4f, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x73, 0x75,
+	0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x12, 0x2a, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e,
+	0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f,
+	0x6e, 0x55, 0x6e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x64, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f,
+	0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x75, 0x63, 0x63, 0x65,
+	0x73, 0x73, 0x22, 0x00, 0x12, 0x59, 0x0a, 0x10, 0x4f, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f,
+	0x6e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x12, 0x25, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e,
+	0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f,
+	0x6e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+	0x1c, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32,
+	0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x00, 0x12,
+	0x5d, 0x0a, 0x12, 0x4f, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x44, 0x69, 0x73, 0x63,
+	0x61, 0x72, 0x64, 0x65, 0x64, 0x12, 0x27, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68,
+	0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x44, 0x69,
+	0x73, 0x63, 0x61, 0x72, 0x64, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c,
+	0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e,
+	0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x00, 0x12, 0x5d,
+	0x0a, 0x12, 0x4f, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x6b, 0x65, 0x6e,
+	0x6f, 0x76, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f,
+	0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x6b,
+	0x65, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e,
+	0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x45,
+	0x6d, 0x70, 0x74, 0x79, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x00, 0x12, 0x5f, 0x0a,
+	0x13, 0x4f, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e,
+	0x61, 0x74, 0x65, 0x64, 0x12, 0x28, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f,
+	0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x72,
+	0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c,
+	0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e,
+	0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x00, 0x12, 0x5b,
+	0x0a, 0x10, 0x4f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69,
+	0x73, 0x68, 0x12, 0x25, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b,
+	0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69,
+	0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x65, 0x6d, 0x71, 0x78,
+	0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65,
+	0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5d, 0x0a, 0x12, 0x4f,
+	0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x65,
+	0x64, 0x12, 0x27, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e,
+	0x76, 0x32, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65,
+	0x72, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x65, 0x6d, 0x71,
+	0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x6d, 0x70, 0x74,
+	0x79, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x00, 0x12, 0x59, 0x0a, 0x10, 0x4f, 0x6e,
+	0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x44, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x12, 0x25,
+	0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e,
+	0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x44, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68,
+	0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x75, 0x63, 0x63,
+	0x65, 0x73, 0x73, 0x22, 0x00, 0x12, 0x55, 0x0a, 0x0e, 0x4f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61,
+	0x67, 0x65, 0x41, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x23, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65,
+	0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+	0x41, 0x63, 0x6b, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x65,
+	0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x6d,
+	0x70, 0x74, 0x79, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x00, 0x42, 0x49, 0x0a, 0x0e,
+	0x69, 0x6f, 0x2e, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0x42, 0x0f,
+	0x45, 0x6d, 0x71, 0x78, 0x45, 0x78, 0x48, 0x6f, 0x6f, 0x6b, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50,
+	0x01, 0x5a, 0x13, 0x65, 0x6d, 0x71, 0x78, 0x2e, 0x69, 0x6f, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f,
+	0x65, 0x78, 0x68, 0x6f, 0x6f, 0x6b, 0xaa, 0x02, 0x0e, 0x45, 0x6d, 0x71, 0x78, 0x2e, 0x45, 0x78,
+	0x68, 0x6f, 0x6f, 0x6b, 0x2e, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+	file_protobuf_exhook_proto_rawDescOnce sync.Once
+	file_protobuf_exhook_proto_rawDescData = file_protobuf_exhook_proto_rawDesc
+)
+
+func file_protobuf_exhook_proto_rawDescGZIP() []byte {
+	file_protobuf_exhook_proto_rawDescOnce.Do(func() {
+		file_protobuf_exhook_proto_rawDescData = protoimpl.X.CompressGZIP(file_protobuf_exhook_proto_rawDescData)
+	})
+	return file_protobuf_exhook_proto_rawDescData
+}
+
+var file_protobuf_exhook_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
+var file_protobuf_exhook_proto_msgTypes = make([]protoimpl.MessageInfo, 34)
+var file_protobuf_exhook_proto_goTypes = []interface{}{
+	(ClientAuthorizeRequest_AuthorizeReqType)(0), // 0: emqx.exhook.v2.ClientAuthorizeRequest.AuthorizeReqType
+	(ValuedResponse_ResponsedType)(0),            // 1: emqx.exhook.v2.ValuedResponse.ResponsedType
+	(*ProviderLoadedRequest)(nil),                // 2: emqx.exhook.v2.ProviderLoadedRequest
+	(*ProviderUnloadedRequest)(nil),              // 3: emqx.exhook.v2.ProviderUnloadedRequest
+	(*ClientConnectRequest)(nil),                 // 4: emqx.exhook.v2.ClientConnectRequest
+	(*ClientConnackRequest)(nil),                 // 5: emqx.exhook.v2.ClientConnackRequest
+	(*ClientConnectedRequest)(nil),               // 6: emqx.exhook.v2.ClientConnectedRequest
+	(*ClientDisconnectedRequest)(nil),            // 7: emqx.exhook.v2.ClientDisconnectedRequest
+	(*ClientAuthenticateRequest)(nil),            // 8: emqx.exhook.v2.ClientAuthenticateRequest
+	(*ClientAuthorizeRequest)(nil),               // 9: emqx.exhook.v2.ClientAuthorizeRequest
+	(*ClientSubscribeRequest)(nil),               // 10: emqx.exhook.v2.ClientSubscribeRequest
+	(*ClientUnsubscribeRequest)(nil),             // 11: emqx.exhook.v2.ClientUnsubscribeRequest
+	(*SessionCreatedRequest)(nil),                // 12: emqx.exhook.v2.SessionCreatedRequest
+	(*SessionSubscribedRequest)(nil),             // 13: emqx.exhook.v2.SessionSubscribedRequest
+	(*SessionUnsubscribedRequest)(nil),           // 14: emqx.exhook.v2.SessionUnsubscribedRequest
+	(*SessionResumedRequest)(nil),                // 15: emqx.exhook.v2.SessionResumedRequest
+	(*SessionDiscardedRequest)(nil),              // 16: emqx.exhook.v2.SessionDiscardedRequest
+	(*SessionTakenoverRequest)(nil),              // 17: emqx.exhook.v2.SessionTakenoverRequest
+	(*SessionTerminatedRequest)(nil),             // 18: emqx.exhook.v2.SessionTerminatedRequest
+	(*MessagePublishRequest)(nil),                // 19: emqx.exhook.v2.MessagePublishRequest
+	(*MessageDeliveredRequest)(nil),              // 20: emqx.exhook.v2.MessageDeliveredRequest
+	(*MessageDroppedRequest)(nil),                // 21: emqx.exhook.v2.MessageDroppedRequest
+	(*MessageAckedRequest)(nil),                  // 22: emqx.exhook.v2.MessageAckedRequest
+	(*LoadedResponse)(nil),                       // 23: emqx.exhook.v2.LoadedResponse
+	(*ValuedResponse)(nil),                       // 24: emqx.exhook.v2.ValuedResponse
+	(*EmptySuccess)(nil),                         // 25: emqx.exhook.v2.EmptySuccess
+	(*BrokerInfo)(nil),                           // 26: emqx.exhook.v2.BrokerInfo
+	(*HookSpec)(nil),                             // 27: emqx.exhook.v2.HookSpec
+	(*ConnInfo)(nil),                             // 28: emqx.exhook.v2.ConnInfo
+	(*ClientInfo)(nil),                           // 29: emqx.exhook.v2.ClientInfo
+	(*Message)(nil),                              // 30: emqx.exhook.v2.Message
+	(*Property)(nil),                             // 31: emqx.exhook.v2.Property
+	(*TopicFilter)(nil),                          // 32: emqx.exhook.v2.TopicFilter
+	(*SubOpts)(nil),                              // 33: emqx.exhook.v2.SubOpts
+	(*RequestMeta)(nil),                          // 34: emqx.exhook.v2.RequestMeta
+	nil,                                          // 35: emqx.exhook.v2.Message.HeadersEntry
+}
+var file_protobuf_exhook_proto_depIdxs = []int32{
+	26, // 0: emqx.exhook.v2.ProviderLoadedRequest.broker:type_name -> emqx.exhook.v2.BrokerInfo
+	34, // 1: emqx.exhook.v2.ProviderLoadedRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	34, // 2: emqx.exhook.v2.ProviderUnloadedRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	28, // 3: emqx.exhook.v2.ClientConnectRequest.conninfo:type_name -> emqx.exhook.v2.ConnInfo
+	31, // 4: emqx.exhook.v2.ClientConnectRequest.props:type_name -> emqx.exhook.v2.Property
+	34, // 5: emqx.exhook.v2.ClientConnectRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	28, // 6: emqx.exhook.v2.ClientConnackRequest.conninfo:type_name -> emqx.exhook.v2.ConnInfo
+	31, // 7: emqx.exhook.v2.ClientConnackRequest.props:type_name -> emqx.exhook.v2.Property
+	34, // 8: emqx.exhook.v2.ClientConnackRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	29, // 9: emqx.exhook.v2.ClientConnectedRequest.clientinfo:type_name -> emqx.exhook.v2.ClientInfo
+	34, // 10: emqx.exhook.v2.ClientConnectedRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	29, // 11: emqx.exhook.v2.ClientDisconnectedRequest.clientinfo:type_name -> emqx.exhook.v2.ClientInfo
+	34, // 12: emqx.exhook.v2.ClientDisconnectedRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	29, // 13: emqx.exhook.v2.ClientAuthenticateRequest.clientinfo:type_name -> emqx.exhook.v2.ClientInfo
+	34, // 14: emqx.exhook.v2.ClientAuthenticateRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	29, // 15: emqx.exhook.v2.ClientAuthorizeRequest.clientinfo:type_name -> emqx.exhook.v2.ClientInfo
+	0,  // 16: emqx.exhook.v2.ClientAuthorizeRequest.type:type_name -> emqx.exhook.v2.ClientAuthorizeRequest.AuthorizeReqType
+	34, // 17: emqx.exhook.v2.ClientAuthorizeRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	29, // 18: emqx.exhook.v2.ClientSubscribeRequest.clientinfo:type_name -> emqx.exhook.v2.ClientInfo
+	31, // 19: emqx.exhook.v2.ClientSubscribeRequest.props:type_name -> emqx.exhook.v2.Property
+	32, // 20: emqx.exhook.v2.ClientSubscribeRequest.topic_filters:type_name -> emqx.exhook.v2.TopicFilter
+	34, // 21: emqx.exhook.v2.ClientSubscribeRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	29, // 22: emqx.exhook.v2.ClientUnsubscribeRequest.clientinfo:type_name -> emqx.exhook.v2.ClientInfo
+	31, // 23: emqx.exhook.v2.ClientUnsubscribeRequest.props:type_name -> emqx.exhook.v2.Property
+	32, // 24: emqx.exhook.v2.ClientUnsubscribeRequest.topic_filters:type_name -> emqx.exhook.v2.TopicFilter
+	34, // 25: emqx.exhook.v2.ClientUnsubscribeRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	29, // 26: emqx.exhook.v2.SessionCreatedRequest.clientinfo:type_name -> emqx.exhook.v2.ClientInfo
+	34, // 27: emqx.exhook.v2.SessionCreatedRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	29, // 28: emqx.exhook.v2.SessionSubscribedRequest.clientinfo:type_name -> emqx.exhook.v2.ClientInfo
+	33, // 29: emqx.exhook.v2.SessionSubscribedRequest.subopts:type_name -> emqx.exhook.v2.SubOpts
+	34, // 30: emqx.exhook.v2.SessionSubscribedRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	29, // 31: emqx.exhook.v2.SessionUnsubscribedRequest.clientinfo:type_name -> emqx.exhook.v2.ClientInfo
+	34, // 32: emqx.exhook.v2.SessionUnsubscribedRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	29, // 33: emqx.exhook.v2.SessionResumedRequest.clientinfo:type_name -> emqx.exhook.v2.ClientInfo
+	34, // 34: emqx.exhook.v2.SessionResumedRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	29, // 35: emqx.exhook.v2.SessionDiscardedRequest.clientinfo:type_name -> emqx.exhook.v2.ClientInfo
+	34, // 36: emqx.exhook.v2.SessionDiscardedRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	29, // 37: emqx.exhook.v2.SessionTakenoverRequest.clientinfo:type_name -> emqx.exhook.v2.ClientInfo
+	34, // 38: emqx.exhook.v2.SessionTakenoverRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	29, // 39: emqx.exhook.v2.SessionTerminatedRequest.clientinfo:type_name -> emqx.exhook.v2.ClientInfo
+	34, // 40: emqx.exhook.v2.SessionTerminatedRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	30, // 41: emqx.exhook.v2.MessagePublishRequest.message:type_name -> emqx.exhook.v2.Message
+	34, // 42: emqx.exhook.v2.MessagePublishRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	29, // 43: emqx.exhook.v2.MessageDeliveredRequest.clientinfo:type_name -> emqx.exhook.v2.ClientInfo
+	30, // 44: emqx.exhook.v2.MessageDeliveredRequest.message:type_name -> emqx.exhook.v2.Message
+	34, // 45: emqx.exhook.v2.MessageDeliveredRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	30, // 46: emqx.exhook.v2.MessageDroppedRequest.message:type_name -> emqx.exhook.v2.Message
+	34, // 47: emqx.exhook.v2.MessageDroppedRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	29, // 48: emqx.exhook.v2.MessageAckedRequest.clientinfo:type_name -> emqx.exhook.v2.ClientInfo
+	30, // 49: emqx.exhook.v2.MessageAckedRequest.message:type_name -> emqx.exhook.v2.Message
+	34, // 50: emqx.exhook.v2.MessageAckedRequest.meta:type_name -> emqx.exhook.v2.RequestMeta
+	27, // 51: emqx.exhook.v2.LoadedResponse.hooks:type_name -> emqx.exhook.v2.HookSpec
+	1,  // 52: emqx.exhook.v2.ValuedResponse.type:type_name -> emqx.exhook.v2.ValuedResponse.ResponsedType
+	30, // 53: emqx.exhook.v2.ValuedResponse.message:type_name -> emqx.exhook.v2.Message
+	35, // 54: emqx.exhook.v2.Message.headers:type_name -> emqx.exhook.v2.Message.HeadersEntry
+	2,  // 55: emqx.exhook.v2.HookProvider.OnProviderLoaded:input_type -> emqx.exhook.v2.ProviderLoadedRequest
+	3,  // 56: emqx.exhook.v2.HookProvider.OnProviderUnloaded:input_type -> emqx.exhook.v2.ProviderUnloadedRequest
+	4,  // 57: emqx.exhook.v2.HookProvider.OnClientConnect:input_type -> emqx.exhook.v2.ClientConnectRequest
+	5,  // 58: emqx.exhook.v2.HookProvider.OnClientConnack:input_type -> emqx.exhook.v2.ClientConnackRequest
+	6,  // 59: emqx.exhook.v2.HookProvider.OnClientConnected:input_type -> emqx.exhook.v2.ClientConnectedRequest
+	7,  // 60: emqx.exhook.v2.HookProvider.OnClientDisconnected:input_type -> emqx.exhook.v2.ClientDisconnectedRequest
+	8,  // 61: emqx.exhook.v2.HookProvider.OnClientAuthenticate:input_type -> emqx.exhook.v2.ClientAuthenticateRequest
+	9,  // 62: emqx.exhook.v2.HookProvider.OnClientAuthorize:input_type -> emqx.exhook.v2.ClientAuthorizeRequest
+	10, // 63: emqx.exhook.v2.HookProvider.OnClientSubscribe:input_type -> emqx.exhook.v2.ClientSubscribeRequest
+	11, // 64: emqx.exhook.v2.HookProvider.OnClientUnsubscribe:input_type -> emqx.exhook.v2.ClientUnsubscribeRequest
+	12, // 65: emqx.exhook.v2.HookProvider.OnSessionCreated:input_type -> emqx.exhook.v2.SessionCreatedRequest
+	13, // 66: emqx.exhook.v2.HookProvider.OnSessionSubscribed:input_type -> emqx.exhook.v2.SessionSubscribedRequest
+	14, // 67: emqx.exhook.v2.HookProvider.OnSessionUnsubscribed:input_type -> emqx.exhook.v2.SessionUnsubscribedRequest
+	15, // 68: emqx.exhook.v2.HookProvider.OnSessionResumed:input_type -> emqx.exhook.v2.SessionResumedRequest
+	16, // 69: emqx.exhook.v2.HookProvider.OnSessionDiscarded:input_type -> emqx.exhook.v2.SessionDiscardedRequest
+	17, // 70: emqx.exhook.v2.HookProvider.OnSessionTakenover:input_type -> emqx.exhook.v2.SessionTakenoverRequest
+	18, // 71: emqx.exhook.v2.HookProvider.OnSessionTerminated:input_type -> emqx.exhook.v2.SessionTerminatedRequest
+	19, // 72: emqx.exhook.v2.HookProvider.OnMessagePublish:input_type -> emqx.exhook.v2.MessagePublishRequest
+	20, // 73: emqx.exhook.v2.HookProvider.OnMessageDelivered:input_type -> emqx.exhook.v2.MessageDeliveredRequest
+	21, // 74: emqx.exhook.v2.HookProvider.OnMessageDropped:input_type -> emqx.exhook.v2.MessageDroppedRequest
+	22, // 75: emqx.exhook.v2.HookProvider.OnMessageAcked:input_type -> emqx.exhook.v2.MessageAckedRequest
+	23, // 76: emqx.exhook.v2.HookProvider.OnProviderLoaded:output_type -> emqx.exhook.v2.LoadedResponse
+	25, // 77: emqx.exhook.v2.HookProvider.OnProviderUnloaded:output_type -> emqx.exhook.v2.EmptySuccess
+	25, // 78: emqx.exhook.v2.HookProvider.OnClientConnect:output_type -> emqx.exhook.v2.EmptySuccess
+	25, // 79: emqx.exhook.v2.HookProvider.OnClientConnack:output_type -> emqx.exhook.v2.EmptySuccess
+	25, // 80: emqx.exhook.v2.HookProvider.OnClientConnected:output_type -> emqx.exhook.v2.EmptySuccess
+	25, // 81: emqx.exhook.v2.HookProvider.OnClientDisconnected:output_type -> emqx.exhook.v2.EmptySuccess
+	24, // 82: emqx.exhook.v2.HookProvider.OnClientAuthenticate:output_type -> emqx.exhook.v2.ValuedResponse
+	24, // 83: emqx.exhook.v2.HookProvider.OnClientAuthorize:output_type -> emqx.exhook.v2.ValuedResponse
+	25, // 84: emqx.exhook.v2.HookProvider.OnClientSubscribe:output_type -> emqx.exhook.v2.EmptySuccess
+	25, // 85: emqx.exhook.v2.HookProvider.OnClientUnsubscribe:output_type -> emqx.exhook.v2.EmptySuccess
+	25, // 86: emqx.exhook.v2.HookProvider.OnSessionCreated:output_type -> emqx.exhook.v2.EmptySuccess
+	25, // 87: emqx.exhook.v2.HookProvider.OnSessionSubscribed:output_type -> emqx.exhook.v2.EmptySuccess
+	25, // 88: emqx.exhook.v2.HookProvider.OnSessionUnsubscribed:output_type -> emqx.exhook.v2.EmptySuccess
+	25, // 89: emqx.exhook.v2.HookProvider.OnSessionResumed:output_type -> emqx.exhook.v2.EmptySuccess
+	25, // 90: emqx.exhook.v2.HookProvider.OnSessionDiscarded:output_type -> emqx.exhook.v2.EmptySuccess
+	25, // 91: emqx.exhook.v2.HookProvider.OnSessionTakenover:output_type -> emqx.exhook.v2.EmptySuccess
+	25, // 92: emqx.exhook.v2.HookProvider.OnSessionTerminated:output_type -> emqx.exhook.v2.EmptySuccess
+	24, // 93: emqx.exhook.v2.HookProvider.OnMessagePublish:output_type -> emqx.exhook.v2.ValuedResponse
+	25, // 94: emqx.exhook.v2.HookProvider.OnMessageDelivered:output_type -> emqx.exhook.v2.EmptySuccess
+	25, // 95: emqx.exhook.v2.HookProvider.OnMessageDropped:output_type -> emqx.exhook.v2.EmptySuccess
+	25, // 96: emqx.exhook.v2.HookProvider.OnMessageAcked:output_type -> emqx.exhook.v2.EmptySuccess
+	76, // [76:97] is the sub-list for method output_type
+	55, // [55:76] is the sub-list for method input_type
+	55, // [55:55] is the sub-list for extension type_name
+	55, // [55:55] is the sub-list for extension extendee
+	0,  // [0:55] is the sub-list for field type_name
+}
+
+func init() { file_protobuf_exhook_proto_init() }
+func file_protobuf_exhook_proto_init() {
+	if File_protobuf_exhook_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_protobuf_exhook_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ProviderLoadedRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ProviderUnloadedRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ClientConnectRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ClientConnackRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ClientConnectedRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ClientDisconnectedRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ClientAuthenticateRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ClientAuthorizeRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ClientSubscribeRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ClientUnsubscribeRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*SessionCreatedRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*SessionSubscribedRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*SessionUnsubscribedRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*SessionResumedRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*SessionDiscardedRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*SessionTakenoverRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*SessionTerminatedRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*MessagePublishRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*MessageDeliveredRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*MessageDroppedRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*MessageAckedRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*LoadedResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ValuedResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*EmptySuccess); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*BrokerInfo); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*HookSpec); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ConnInfo); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ClientInfo); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Message); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Property); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*TopicFilter); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*SubOpts); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_protobuf_exhook_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*RequestMeta); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	file_protobuf_exhook_proto_msgTypes[22].OneofWrappers = []interface{}{
+		(*ValuedResponse_BoolResult)(nil),
+		(*ValuedResponse_Message)(nil),
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_protobuf_exhook_proto_rawDesc,
+			NumEnums:      2,
+			NumMessages:   34,
+			NumExtensions: 0,
+			NumServices:   1,
+		},
+		GoTypes:           file_protobuf_exhook_proto_goTypes,
+		DependencyIndexes: file_protobuf_exhook_proto_depIdxs,
+		EnumInfos:         file_protobuf_exhook_proto_enumTypes,
+		MessageInfos:      file_protobuf_exhook_proto_msgTypes,
+	}.Build()
+	File_protobuf_exhook_proto = out.File
+	file_protobuf_exhook_proto_rawDesc = nil
+	file_protobuf_exhook_proto_goTypes = nil
+	file_protobuf_exhook_proto_depIdxs = nil
+}

+ 499 - 0
services/emqx-agent/protobuf/exhook.proto

@@ -0,0 +1,499 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2020-2022 EMQ Technologies Co., Ltd. All Rights Reserved.
+//
+// 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.
+//------------------------------------------------------------------------------
+
+syntax = "proto3";
+
+option csharp_namespace = "Emqx.Exhook.V2";
+option go_package = "emqx.io/grpc/exhook";
+option java_multiple_files = true;
+option java_package = "io.emqx.exhook";
+option java_outer_classname = "EmqxExHookProto";
+
+// The exhook proto version should be fixed as `v2` in EMQX v5.x
+// to make sure the exhook proto version is compatible
+package emqx.exhook.v2;
+
+service HookProvider {
+
+  rpc OnProviderLoaded(ProviderLoadedRequest) returns (LoadedResponse) {};
+
+  rpc OnProviderUnloaded(ProviderUnloadedRequest) returns (EmptySuccess) {};
+
+  rpc OnClientConnect(ClientConnectRequest) returns (EmptySuccess) {};
+
+  rpc OnClientConnack(ClientConnackRequest) returns (EmptySuccess) {};
+
+  rpc OnClientConnected(ClientConnectedRequest) returns (EmptySuccess) {};
+
+  rpc OnClientDisconnected(ClientDisconnectedRequest) returns (EmptySuccess) {};
+
+  rpc OnClientAuthenticate(ClientAuthenticateRequest) returns (ValuedResponse) {};
+
+  rpc OnClientAuthorize(ClientAuthorizeRequest) returns (ValuedResponse) {};
+
+  rpc OnClientSubscribe(ClientSubscribeRequest) returns (EmptySuccess) {};
+
+  rpc OnClientUnsubscribe(ClientUnsubscribeRequest) returns (EmptySuccess) {};
+
+  rpc OnSessionCreated(SessionCreatedRequest) returns (EmptySuccess) {};
+
+  rpc OnSessionSubscribed(SessionSubscribedRequest) returns (EmptySuccess) {};
+
+  rpc OnSessionUnsubscribed(SessionUnsubscribedRequest) returns (EmptySuccess) {};
+
+  rpc OnSessionResumed(SessionResumedRequest) returns (EmptySuccess) {};
+
+  rpc OnSessionDiscarded(SessionDiscardedRequest) returns (EmptySuccess) {};
+
+  rpc OnSessionTakenover(SessionTakenoverRequest) returns (EmptySuccess) {};
+
+  rpc OnSessionTerminated(SessionTerminatedRequest) returns (EmptySuccess) {};
+
+  rpc OnMessagePublish(MessagePublishRequest) returns (ValuedResponse) {};
+
+  rpc OnMessageDelivered(MessageDeliveredRequest) returns (EmptySuccess) {};
+
+  rpc OnMessageDropped(MessageDroppedRequest) returns (EmptySuccess) {};
+
+  rpc OnMessageAcked(MessageAckedRequest) returns (EmptySuccess) {};
+}
+
+//------------------------------------------------------------------------------
+// Request
+//------------------------------------------------------------------------------
+
+message ProviderLoadedRequest {
+
+  BrokerInfo broker = 1;
+
+  RequestMeta meta = 2;
+}
+
+message ProviderUnloadedRequest {
+
+  RequestMeta meta = 1;
+}
+
+message ClientConnectRequest {
+
+  ConnInfo conninfo = 1;
+
+  // MQTT CONNECT packet's properties (MQTT v5.0)
+  //
+  // It should be empty on MQTT v3.1.1/v3.1 or others protocol
+  repeated Property props = 2;
+
+  RequestMeta meta = 3;
+}
+
+message ClientConnackRequest {
+
+  ConnInfo conninfo = 1;
+
+  string result_code = 2;
+
+  repeated Property props = 3;
+
+  RequestMeta meta = 4;
+}
+
+message ClientConnectedRequest {
+
+  ClientInfo clientinfo = 1;
+
+  RequestMeta meta = 2;
+}
+
+message ClientDisconnectedRequest {
+
+  ClientInfo clientinfo = 1;
+
+  string reason = 2;
+
+  RequestMeta meta = 3;
+}
+
+message ClientAuthenticateRequest {
+
+  ClientInfo clientinfo = 1;
+
+  bool result = 2;
+
+  RequestMeta meta = 3;
+}
+
+message ClientAuthorizeRequest {
+
+  ClientInfo clientinfo = 1;
+
+  enum AuthorizeReqType {
+
+    PUBLISH = 0;
+
+    SUBSCRIBE = 1;
+  }
+
+  AuthorizeReqType type = 2;
+
+  string topic = 3;
+
+  bool result = 4;
+
+  RequestMeta meta = 5;
+}
+
+message ClientSubscribeRequest {
+
+  ClientInfo clientinfo = 1;
+
+  repeated Property props = 2;
+
+  repeated TopicFilter topic_filters = 3;
+
+  RequestMeta meta = 4;
+}
+
+message ClientUnsubscribeRequest {
+
+  ClientInfo clientinfo = 1;
+
+  repeated Property props = 2;
+
+  repeated TopicFilter topic_filters = 3;
+
+  RequestMeta meta = 4;
+}
+
+message SessionCreatedRequest {
+
+  ClientInfo clientinfo = 1;
+
+  RequestMeta meta = 2;
+}
+
+message SessionSubscribedRequest {
+
+  ClientInfo clientinfo = 1;
+
+  string topic = 2;
+
+  SubOpts subopts = 3;
+
+  RequestMeta meta = 4;
+}
+
+message SessionUnsubscribedRequest {
+
+  ClientInfo clientinfo = 1;
+
+  string topic = 2;
+
+  RequestMeta meta = 3;
+}
+
+message SessionResumedRequest {
+
+  ClientInfo clientinfo = 1;
+
+  RequestMeta meta = 2;
+}
+
+message SessionDiscardedRequest {
+
+  ClientInfo clientinfo = 1;
+
+  RequestMeta meta = 2;
+}
+
+message SessionTakenoverRequest {
+
+  ClientInfo clientinfo = 1;
+
+  RequestMeta meta = 2;
+}
+
+message SessionTerminatedRequest {
+
+  ClientInfo clientinfo = 1;
+
+  string reason = 2;
+
+  RequestMeta meta = 3;
+}
+
+message MessagePublishRequest {
+
+  Message message = 1;
+
+  RequestMeta meta = 2;
+}
+
+message MessageDeliveredRequest {
+
+  ClientInfo clientinfo = 1;
+
+  Message message = 2;
+
+  RequestMeta meta = 3;
+}
+
+message MessageDroppedRequest {
+
+  Message message = 1;
+
+  string reason = 2;
+
+  RequestMeta meta = 3;
+}
+
+message MessageAckedRequest {
+
+  ClientInfo clientinfo = 1;
+
+  Message message = 2;
+
+  RequestMeta meta = 3;
+}
+
+//------------------------------------------------------------------------------
+// Response
+//------------------------------------------------------------------------------
+
+// Responsed by `ProviderLoadedRequest`
+
+message LoadedResponse {
+
+  repeated HookSpec hooks = 1;
+}
+
+// Responsed by `ClientAuthenticateRequest` `ClientAuthorizeRequest` `MessagePublishRequest`
+
+message ValuedResponse {
+
+  // The responded value type
+  //  - contiune: Use the responded value and execute the next hook
+  //  - ignore: Ignore the responded value
+  //  - stop_and_return: Use the responded value and stop the chain executing
+  enum ResponsedType {
+
+    CONTINUE = 0;
+
+    IGNORE = 1;
+
+    STOP_AND_RETURN = 2;
+  }
+
+  ResponsedType type = 1;
+
+  oneof value {
+
+    // Boolean result, used on the 'client.authenticate', 'client.authorize' hooks
+    bool bool_result = 3;
+
+    // Message result, used on the 'message.*' hooks
+    Message message = 4;
+  }
+}
+
+// no Response by other Requests
+
+message EmptySuccess {}
+
+//------------------------------------------------------------------------------
+// Basic data types
+//------------------------------------------------------------------------------
+
+message BrokerInfo {
+
+  string version = 1;
+
+  string sysdescr = 2;
+
+  int64 uptime = 3;
+
+  string datetime = 4;
+}
+
+
+message HookSpec {
+
+  // The registered hooks name
+  //
+  // Available value:
+  //   "client.connect",      "client.connack"
+  //   "client.connected",    "client.disconnected"
+  //   "client.authenticate", "client.authorize"
+  //   "client.subscribe",    "client.unsubscribe"
+  //
+  //   "session.created",      "session.subscribed"
+  //   "session.unsubscribed", "session.resumed"
+  //   "session.discarded",    "session.takenover"
+  //   "session.terminated"
+  //
+  //   "message.publish", "message.delivered"
+  //   "message.acked",   "message.dropped"
+  string name = 1;
+
+  // The topic filters for message hooks
+  repeated string topics = 2;
+}
+
+message ConnInfo {
+
+  string node = 1;
+
+  string clientid = 2;
+
+  string username = 3;
+
+  string peerhost = 4;
+
+  uint32 sockport = 5;
+
+  string proto_name = 6;
+
+  string proto_ver = 7;
+
+  uint32 keepalive = 8;
+}
+
+message ClientInfo {
+
+  string node = 1;
+
+  string clientid = 2;
+
+  string username = 3;
+
+  string password = 4;
+
+  string peerhost = 5;
+
+  uint32 sockport = 6;
+
+  string protocol = 7;
+
+  string mountpoint = 8;
+
+  bool  is_superuser = 9;
+
+  bool  anonymous = 10;
+
+  // common name of client TLS cert
+  string cn = 11;
+
+  // subject of client TLS cert
+  string dn = 12;
+}
+
+message Message {
+
+  string node = 1;
+
+  string id = 2;
+
+  uint32 qos = 3;
+
+  string from = 4;
+
+  string topic = 5;
+
+  bytes  payload = 6;
+
+  uint64 timestamp = 7;
+
+  // The key of header can be:
+  //  - username:
+  //    * Readonly
+  //    * The username of sender client
+  //    * Value type: utf8 string
+  //  - protocol:
+  //    * Readonly
+  //    * The protocol name of sender client
+  //    * Value type: string enum with "mqtt", "mqtt-sn", ...
+  //  - peerhost:
+  //    * Readonly
+  //    * The peerhost of sender client
+  //    * Value type: ip address string
+  //  - allow_publish:
+  //    * Writable
+  //    * Whether to allow the message to be published by emqx
+  //    * Value type: string enum with "true", "false", default is "true"
+  //
+  // Notes: All header may be missing, which means that the message does not
+  //   carry these headers. We can guarantee that clients coming from MQTT,
+  //   MQTT-SN, CoAP, LwM2M and other natively supported protocol clients will
+  //   carry these headers, but there is no guarantee that messages published
+  //   by other means will do, e.g. messages published by HTTP-API
+  map<string, string> headers = 8;
+}
+
+message Property {
+
+  string name = 1;
+
+  string value = 2;
+}
+
+message TopicFilter {
+
+  string name = 1;
+
+  uint32 qos = 2;
+}
+
+message SubOpts {
+
+  // The QoS level
+  uint32 qos = 1;
+
+  // The group name for shared subscription
+  string share = 2;
+
+  // The Retain Handling option (MQTT v5.0)
+  //
+  //  0 = Send retained messages at the time of the subscribe
+  //  1 = Send retained messages at subscribe only if the subscription does
+  //       not currently exist
+  //  2 = Do not send retained messages at the time of the subscribe
+  uint32 rh = 3;
+
+  // The Retain as Published option (MQTT v5.0)
+  //
+  //  If 1, Application Messages forwarded using this subscription keep the
+  //        RETAIN flag they were published with.
+  //  If 0, Application Messages forwarded using this subscription have the
+  //        RETAIN flag set to 0.
+  // Retained messages sent when the subscription is established have the RETAIN flag set to 1.
+  uint32 rap = 4;
+
+  // The No Local option (MQTT v5.0)
+  //
+  // If the value is 1, Application Messages MUST NOT be forwarded to a
+  // connection with a ClientID equal to the ClientID of the publishing
+  uint32 nl = 5;
+}
+
+message RequestMeta {
+
+  string node = 1;
+
+  string version = 2;
+
+  string sysdescr = 3;
+
+  string cluster_name = 4;
+}

+ 868 - 0
services/emqx-agent/protobuf/exhook_grpc.pb.go

@@ -0,0 +1,868 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2020-2022 EMQ Technologies Co., Ltd. All Rights Reserved.
+//
+// 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.
+//------------------------------------------------------------------------------
+
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.3.0
+// - protoc             v4.25.1
+// source: protobuf/exhook.proto
+
+// The exhook proto version should be fixed as `v2` in EMQX v5.x
+// to make sure the exhook proto version is compatible
+
+package exhook
+
+import (
+	context "context"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
+
+const (
+	HookProvider_OnProviderLoaded_FullMethodName      = "/emqx.exhook.v2.HookProvider/OnProviderLoaded"
+	HookProvider_OnProviderUnloaded_FullMethodName    = "/emqx.exhook.v2.HookProvider/OnProviderUnloaded"
+	HookProvider_OnClientConnect_FullMethodName       = "/emqx.exhook.v2.HookProvider/OnClientConnect"
+	HookProvider_OnClientConnack_FullMethodName       = "/emqx.exhook.v2.HookProvider/OnClientConnack"
+	HookProvider_OnClientConnected_FullMethodName     = "/emqx.exhook.v2.HookProvider/OnClientConnected"
+	HookProvider_OnClientDisconnected_FullMethodName  = "/emqx.exhook.v2.HookProvider/OnClientDisconnected"
+	HookProvider_OnClientAuthenticate_FullMethodName  = "/emqx.exhook.v2.HookProvider/OnClientAuthenticate"
+	HookProvider_OnClientAuthorize_FullMethodName     = "/emqx.exhook.v2.HookProvider/OnClientAuthorize"
+	HookProvider_OnClientSubscribe_FullMethodName     = "/emqx.exhook.v2.HookProvider/OnClientSubscribe"
+	HookProvider_OnClientUnsubscribe_FullMethodName   = "/emqx.exhook.v2.HookProvider/OnClientUnsubscribe"
+	HookProvider_OnSessionCreated_FullMethodName      = "/emqx.exhook.v2.HookProvider/OnSessionCreated"
+	HookProvider_OnSessionSubscribed_FullMethodName   = "/emqx.exhook.v2.HookProvider/OnSessionSubscribed"
+	HookProvider_OnSessionUnsubscribed_FullMethodName = "/emqx.exhook.v2.HookProvider/OnSessionUnsubscribed"
+	HookProvider_OnSessionResumed_FullMethodName      = "/emqx.exhook.v2.HookProvider/OnSessionResumed"
+	HookProvider_OnSessionDiscarded_FullMethodName    = "/emqx.exhook.v2.HookProvider/OnSessionDiscarded"
+	HookProvider_OnSessionTakenover_FullMethodName    = "/emqx.exhook.v2.HookProvider/OnSessionTakenover"
+	HookProvider_OnSessionTerminated_FullMethodName   = "/emqx.exhook.v2.HookProvider/OnSessionTerminated"
+	HookProvider_OnMessagePublish_FullMethodName      = "/emqx.exhook.v2.HookProvider/OnMessagePublish"
+	HookProvider_OnMessageDelivered_FullMethodName    = "/emqx.exhook.v2.HookProvider/OnMessageDelivered"
+	HookProvider_OnMessageDropped_FullMethodName      = "/emqx.exhook.v2.HookProvider/OnMessageDropped"
+	HookProvider_OnMessageAcked_FullMethodName        = "/emqx.exhook.v2.HookProvider/OnMessageAcked"
+)
+
+// HookProviderClient is the client API for HookProvider service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type HookProviderClient interface {
+	OnProviderLoaded(ctx context.Context, in *ProviderLoadedRequest, opts ...grpc.CallOption) (*LoadedResponse, error)
+	OnProviderUnloaded(ctx context.Context, in *ProviderUnloadedRequest, opts ...grpc.CallOption) (*EmptySuccess, error)
+	OnClientConnect(ctx context.Context, in *ClientConnectRequest, opts ...grpc.CallOption) (*EmptySuccess, error)
+	OnClientConnack(ctx context.Context, in *ClientConnackRequest, opts ...grpc.CallOption) (*EmptySuccess, error)
+	OnClientConnected(ctx context.Context, in *ClientConnectedRequest, opts ...grpc.CallOption) (*EmptySuccess, error)
+	OnClientDisconnected(ctx context.Context, in *ClientDisconnectedRequest, opts ...grpc.CallOption) (*EmptySuccess, error)
+	OnClientAuthenticate(ctx context.Context, in *ClientAuthenticateRequest, opts ...grpc.CallOption) (*ValuedResponse, error)
+	OnClientAuthorize(ctx context.Context, in *ClientAuthorizeRequest, opts ...grpc.CallOption) (*ValuedResponse, error)
+	OnClientSubscribe(ctx context.Context, in *ClientSubscribeRequest, opts ...grpc.CallOption) (*EmptySuccess, error)
+	OnClientUnsubscribe(ctx context.Context, in *ClientUnsubscribeRequest, opts ...grpc.CallOption) (*EmptySuccess, error)
+	OnSessionCreated(ctx context.Context, in *SessionCreatedRequest, opts ...grpc.CallOption) (*EmptySuccess, error)
+	OnSessionSubscribed(ctx context.Context, in *SessionSubscribedRequest, opts ...grpc.CallOption) (*EmptySuccess, error)
+	OnSessionUnsubscribed(ctx context.Context, in *SessionUnsubscribedRequest, opts ...grpc.CallOption) (*EmptySuccess, error)
+	OnSessionResumed(ctx context.Context, in *SessionResumedRequest, opts ...grpc.CallOption) (*EmptySuccess, error)
+	OnSessionDiscarded(ctx context.Context, in *SessionDiscardedRequest, opts ...grpc.CallOption) (*EmptySuccess, error)
+	OnSessionTakenover(ctx context.Context, in *SessionTakenoverRequest, opts ...grpc.CallOption) (*EmptySuccess, error)
+	OnSessionTerminated(ctx context.Context, in *SessionTerminatedRequest, opts ...grpc.CallOption) (*EmptySuccess, error)
+	OnMessagePublish(ctx context.Context, in *MessagePublishRequest, opts ...grpc.CallOption) (*ValuedResponse, error)
+	OnMessageDelivered(ctx context.Context, in *MessageDeliveredRequest, opts ...grpc.CallOption) (*EmptySuccess, error)
+	OnMessageDropped(ctx context.Context, in *MessageDroppedRequest, opts ...grpc.CallOption) (*EmptySuccess, error)
+	OnMessageAcked(ctx context.Context, in *MessageAckedRequest, opts ...grpc.CallOption) (*EmptySuccess, error)
+}
+
+type hookProviderClient struct {
+	cc grpc.ClientConnInterface
+}
+
+func NewHookProviderClient(cc grpc.ClientConnInterface) HookProviderClient {
+	return &hookProviderClient{cc}
+}
+
+func (c *hookProviderClient) OnProviderLoaded(ctx context.Context, in *ProviderLoadedRequest, opts ...grpc.CallOption) (*LoadedResponse, error) {
+	out := new(LoadedResponse)
+	err := c.cc.Invoke(ctx, HookProvider_OnProviderLoaded_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnProviderUnloaded(ctx context.Context, in *ProviderUnloadedRequest, opts ...grpc.CallOption) (*EmptySuccess, error) {
+	out := new(EmptySuccess)
+	err := c.cc.Invoke(ctx, HookProvider_OnProviderUnloaded_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnClientConnect(ctx context.Context, in *ClientConnectRequest, opts ...grpc.CallOption) (*EmptySuccess, error) {
+	out := new(EmptySuccess)
+	err := c.cc.Invoke(ctx, HookProvider_OnClientConnect_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnClientConnack(ctx context.Context, in *ClientConnackRequest, opts ...grpc.CallOption) (*EmptySuccess, error) {
+	out := new(EmptySuccess)
+	err := c.cc.Invoke(ctx, HookProvider_OnClientConnack_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnClientConnected(ctx context.Context, in *ClientConnectedRequest, opts ...grpc.CallOption) (*EmptySuccess, error) {
+	out := new(EmptySuccess)
+	err := c.cc.Invoke(ctx, HookProvider_OnClientConnected_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnClientDisconnected(ctx context.Context, in *ClientDisconnectedRequest, opts ...grpc.CallOption) (*EmptySuccess, error) {
+	out := new(EmptySuccess)
+	err := c.cc.Invoke(ctx, HookProvider_OnClientDisconnected_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnClientAuthenticate(ctx context.Context, in *ClientAuthenticateRequest, opts ...grpc.CallOption) (*ValuedResponse, error) {
+	out := new(ValuedResponse)
+	err := c.cc.Invoke(ctx, HookProvider_OnClientAuthenticate_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnClientAuthorize(ctx context.Context, in *ClientAuthorizeRequest, opts ...grpc.CallOption) (*ValuedResponse, error) {
+	out := new(ValuedResponse)
+	err := c.cc.Invoke(ctx, HookProvider_OnClientAuthorize_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnClientSubscribe(ctx context.Context, in *ClientSubscribeRequest, opts ...grpc.CallOption) (*EmptySuccess, error) {
+	out := new(EmptySuccess)
+	err := c.cc.Invoke(ctx, HookProvider_OnClientSubscribe_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnClientUnsubscribe(ctx context.Context, in *ClientUnsubscribeRequest, opts ...grpc.CallOption) (*EmptySuccess, error) {
+	out := new(EmptySuccess)
+	err := c.cc.Invoke(ctx, HookProvider_OnClientUnsubscribe_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnSessionCreated(ctx context.Context, in *SessionCreatedRequest, opts ...grpc.CallOption) (*EmptySuccess, error) {
+	out := new(EmptySuccess)
+	err := c.cc.Invoke(ctx, HookProvider_OnSessionCreated_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnSessionSubscribed(ctx context.Context, in *SessionSubscribedRequest, opts ...grpc.CallOption) (*EmptySuccess, error) {
+	out := new(EmptySuccess)
+	err := c.cc.Invoke(ctx, HookProvider_OnSessionSubscribed_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnSessionUnsubscribed(ctx context.Context, in *SessionUnsubscribedRequest, opts ...grpc.CallOption) (*EmptySuccess, error) {
+	out := new(EmptySuccess)
+	err := c.cc.Invoke(ctx, HookProvider_OnSessionUnsubscribed_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnSessionResumed(ctx context.Context, in *SessionResumedRequest, opts ...grpc.CallOption) (*EmptySuccess, error) {
+	out := new(EmptySuccess)
+	err := c.cc.Invoke(ctx, HookProvider_OnSessionResumed_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnSessionDiscarded(ctx context.Context, in *SessionDiscardedRequest, opts ...grpc.CallOption) (*EmptySuccess, error) {
+	out := new(EmptySuccess)
+	err := c.cc.Invoke(ctx, HookProvider_OnSessionDiscarded_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnSessionTakenover(ctx context.Context, in *SessionTakenoverRequest, opts ...grpc.CallOption) (*EmptySuccess, error) {
+	out := new(EmptySuccess)
+	err := c.cc.Invoke(ctx, HookProvider_OnSessionTakenover_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnSessionTerminated(ctx context.Context, in *SessionTerminatedRequest, opts ...grpc.CallOption) (*EmptySuccess, error) {
+	out := new(EmptySuccess)
+	err := c.cc.Invoke(ctx, HookProvider_OnSessionTerminated_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnMessagePublish(ctx context.Context, in *MessagePublishRequest, opts ...grpc.CallOption) (*ValuedResponse, error) {
+	out := new(ValuedResponse)
+	err := c.cc.Invoke(ctx, HookProvider_OnMessagePublish_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnMessageDelivered(ctx context.Context, in *MessageDeliveredRequest, opts ...grpc.CallOption) (*EmptySuccess, error) {
+	out := new(EmptySuccess)
+	err := c.cc.Invoke(ctx, HookProvider_OnMessageDelivered_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnMessageDropped(ctx context.Context, in *MessageDroppedRequest, opts ...grpc.CallOption) (*EmptySuccess, error) {
+	out := new(EmptySuccess)
+	err := c.cc.Invoke(ctx, HookProvider_OnMessageDropped_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *hookProviderClient) OnMessageAcked(ctx context.Context, in *MessageAckedRequest, opts ...grpc.CallOption) (*EmptySuccess, error) {
+	out := new(EmptySuccess)
+	err := c.cc.Invoke(ctx, HookProvider_OnMessageAcked_FullMethodName, in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// HookProviderServer is the server API for HookProvider service.
+// All implementations must embed UnimplementedHookProviderServer
+// for forward compatibility
+type HookProviderServer interface {
+	OnProviderLoaded(context.Context, *ProviderLoadedRequest) (*LoadedResponse, error)
+	OnProviderUnloaded(context.Context, *ProviderUnloadedRequest) (*EmptySuccess, error)
+	OnClientConnect(context.Context, *ClientConnectRequest) (*EmptySuccess, error)
+	OnClientConnack(context.Context, *ClientConnackRequest) (*EmptySuccess, error)
+	OnClientConnected(context.Context, *ClientConnectedRequest) (*EmptySuccess, error)
+	OnClientDisconnected(context.Context, *ClientDisconnectedRequest) (*EmptySuccess, error)
+	OnClientAuthenticate(context.Context, *ClientAuthenticateRequest) (*ValuedResponse, error)
+	OnClientAuthorize(context.Context, *ClientAuthorizeRequest) (*ValuedResponse, error)
+	OnClientSubscribe(context.Context, *ClientSubscribeRequest) (*EmptySuccess, error)
+	OnClientUnsubscribe(context.Context, *ClientUnsubscribeRequest) (*EmptySuccess, error)
+	OnSessionCreated(context.Context, *SessionCreatedRequest) (*EmptySuccess, error)
+	OnSessionSubscribed(context.Context, *SessionSubscribedRequest) (*EmptySuccess, error)
+	OnSessionUnsubscribed(context.Context, *SessionUnsubscribedRequest) (*EmptySuccess, error)
+	OnSessionResumed(context.Context, *SessionResumedRequest) (*EmptySuccess, error)
+	OnSessionDiscarded(context.Context, *SessionDiscardedRequest) (*EmptySuccess, error)
+	OnSessionTakenover(context.Context, *SessionTakenoverRequest) (*EmptySuccess, error)
+	OnSessionTerminated(context.Context, *SessionTerminatedRequest) (*EmptySuccess, error)
+	OnMessagePublish(context.Context, *MessagePublishRequest) (*ValuedResponse, error)
+	OnMessageDelivered(context.Context, *MessageDeliveredRequest) (*EmptySuccess, error)
+	OnMessageDropped(context.Context, *MessageDroppedRequest) (*EmptySuccess, error)
+	OnMessageAcked(context.Context, *MessageAckedRequest) (*EmptySuccess, error)
+	mustEmbedUnimplementedHookProviderServer()
+}
+
+// UnimplementedHookProviderServer must be embedded to have forward compatible implementations.
+type UnimplementedHookProviderServer struct {
+}
+
+func (UnimplementedHookProviderServer) OnProviderLoaded(context.Context, *ProviderLoadedRequest) (*LoadedResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnProviderLoaded not implemented")
+}
+func (UnimplementedHookProviderServer) OnProviderUnloaded(context.Context, *ProviderUnloadedRequest) (*EmptySuccess, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnProviderUnloaded not implemented")
+}
+func (UnimplementedHookProviderServer) OnClientConnect(context.Context, *ClientConnectRequest) (*EmptySuccess, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnClientConnect not implemented")
+}
+func (UnimplementedHookProviderServer) OnClientConnack(context.Context, *ClientConnackRequest) (*EmptySuccess, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnClientConnack not implemented")
+}
+func (UnimplementedHookProviderServer) OnClientConnected(context.Context, *ClientConnectedRequest) (*EmptySuccess, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnClientConnected not implemented")
+}
+func (UnimplementedHookProviderServer) OnClientDisconnected(context.Context, *ClientDisconnectedRequest) (*EmptySuccess, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnClientDisconnected not implemented")
+}
+func (UnimplementedHookProviderServer) OnClientAuthenticate(context.Context, *ClientAuthenticateRequest) (*ValuedResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnClientAuthenticate not implemented")
+}
+func (UnimplementedHookProviderServer) OnClientAuthorize(context.Context, *ClientAuthorizeRequest) (*ValuedResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnClientAuthorize not implemented")
+}
+func (UnimplementedHookProviderServer) OnClientSubscribe(context.Context, *ClientSubscribeRequest) (*EmptySuccess, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnClientSubscribe not implemented")
+}
+func (UnimplementedHookProviderServer) OnClientUnsubscribe(context.Context, *ClientUnsubscribeRequest) (*EmptySuccess, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnClientUnsubscribe not implemented")
+}
+func (UnimplementedHookProviderServer) OnSessionCreated(context.Context, *SessionCreatedRequest) (*EmptySuccess, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnSessionCreated not implemented")
+}
+func (UnimplementedHookProviderServer) OnSessionSubscribed(context.Context, *SessionSubscribedRequest) (*EmptySuccess, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnSessionSubscribed not implemented")
+}
+func (UnimplementedHookProviderServer) OnSessionUnsubscribed(context.Context, *SessionUnsubscribedRequest) (*EmptySuccess, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnSessionUnsubscribed not implemented")
+}
+func (UnimplementedHookProviderServer) OnSessionResumed(context.Context, *SessionResumedRequest) (*EmptySuccess, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnSessionResumed not implemented")
+}
+func (UnimplementedHookProviderServer) OnSessionDiscarded(context.Context, *SessionDiscardedRequest) (*EmptySuccess, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnSessionDiscarded not implemented")
+}
+func (UnimplementedHookProviderServer) OnSessionTakenover(context.Context, *SessionTakenoverRequest) (*EmptySuccess, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnSessionTakenover not implemented")
+}
+func (UnimplementedHookProviderServer) OnSessionTerminated(context.Context, *SessionTerminatedRequest) (*EmptySuccess, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnSessionTerminated not implemented")
+}
+func (UnimplementedHookProviderServer) OnMessagePublish(context.Context, *MessagePublishRequest) (*ValuedResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnMessagePublish not implemented")
+}
+func (UnimplementedHookProviderServer) OnMessageDelivered(context.Context, *MessageDeliveredRequest) (*EmptySuccess, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnMessageDelivered not implemented")
+}
+func (UnimplementedHookProviderServer) OnMessageDropped(context.Context, *MessageDroppedRequest) (*EmptySuccess, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnMessageDropped not implemented")
+}
+func (UnimplementedHookProviderServer) OnMessageAcked(context.Context, *MessageAckedRequest) (*EmptySuccess, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method OnMessageAcked not implemented")
+}
+func (UnimplementedHookProviderServer) mustEmbedUnimplementedHookProviderServer() {}
+
+// UnsafeHookProviderServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to HookProviderServer will
+// result in compilation errors.
+type UnsafeHookProviderServer interface {
+	mustEmbedUnimplementedHookProviderServer()
+}
+
+func RegisterHookProviderServer(s grpc.ServiceRegistrar, srv HookProviderServer) {
+	s.RegisterService(&HookProvider_ServiceDesc, srv)
+}
+
+func _HookProvider_OnProviderLoaded_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ProviderLoadedRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnProviderLoaded(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnProviderLoaded_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnProviderLoaded(ctx, req.(*ProviderLoadedRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnProviderUnloaded_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ProviderUnloadedRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnProviderUnloaded(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnProviderUnloaded_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnProviderUnloaded(ctx, req.(*ProviderUnloadedRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnClientConnect_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ClientConnectRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnClientConnect(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnClientConnect_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnClientConnect(ctx, req.(*ClientConnectRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnClientConnack_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ClientConnackRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnClientConnack(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnClientConnack_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnClientConnack(ctx, req.(*ClientConnackRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnClientConnected_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ClientConnectedRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnClientConnected(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnClientConnected_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnClientConnected(ctx, req.(*ClientConnectedRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnClientDisconnected_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ClientDisconnectedRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnClientDisconnected(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnClientDisconnected_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnClientDisconnected(ctx, req.(*ClientDisconnectedRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnClientAuthenticate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ClientAuthenticateRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnClientAuthenticate(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnClientAuthenticate_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnClientAuthenticate(ctx, req.(*ClientAuthenticateRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnClientAuthorize_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ClientAuthorizeRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnClientAuthorize(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnClientAuthorize_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnClientAuthorize(ctx, req.(*ClientAuthorizeRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnClientSubscribe_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ClientSubscribeRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnClientSubscribe(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnClientSubscribe_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnClientSubscribe(ctx, req.(*ClientSubscribeRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnClientUnsubscribe_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ClientUnsubscribeRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnClientUnsubscribe(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnClientUnsubscribe_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnClientUnsubscribe(ctx, req.(*ClientUnsubscribeRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnSessionCreated_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(SessionCreatedRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnSessionCreated(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnSessionCreated_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnSessionCreated(ctx, req.(*SessionCreatedRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnSessionSubscribed_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(SessionSubscribedRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnSessionSubscribed(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnSessionSubscribed_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnSessionSubscribed(ctx, req.(*SessionSubscribedRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnSessionUnsubscribed_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(SessionUnsubscribedRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnSessionUnsubscribed(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnSessionUnsubscribed_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnSessionUnsubscribed(ctx, req.(*SessionUnsubscribedRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnSessionResumed_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(SessionResumedRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnSessionResumed(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnSessionResumed_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnSessionResumed(ctx, req.(*SessionResumedRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnSessionDiscarded_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(SessionDiscardedRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnSessionDiscarded(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnSessionDiscarded_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnSessionDiscarded(ctx, req.(*SessionDiscardedRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnSessionTakenover_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(SessionTakenoverRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnSessionTakenover(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnSessionTakenover_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnSessionTakenover(ctx, req.(*SessionTakenoverRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnSessionTerminated_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(SessionTerminatedRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnSessionTerminated(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnSessionTerminated_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnSessionTerminated(ctx, req.(*SessionTerminatedRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnMessagePublish_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(MessagePublishRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnMessagePublish(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnMessagePublish_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnMessagePublish(ctx, req.(*MessagePublishRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnMessageDelivered_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(MessageDeliveredRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnMessageDelivered(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnMessageDelivered_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnMessageDelivered(ctx, req.(*MessageDeliveredRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnMessageDropped_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(MessageDroppedRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnMessageDropped(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnMessageDropped_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnMessageDropped(ctx, req.(*MessageDroppedRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _HookProvider_OnMessageAcked_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(MessageAckedRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(HookProviderServer).OnMessageAcked(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: HookProvider_OnMessageAcked_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(HookProviderServer).OnMessageAcked(ctx, req.(*MessageAckedRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+// HookProvider_ServiceDesc is the grpc.ServiceDesc for HookProvider service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var HookProvider_ServiceDesc = grpc.ServiceDesc{
+	ServiceName: "emqx.exhook.v2.HookProvider",
+	HandlerType: (*HookProviderServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "OnProviderLoaded",
+			Handler:    _HookProvider_OnProviderLoaded_Handler,
+		},
+		{
+			MethodName: "OnProviderUnloaded",
+			Handler:    _HookProvider_OnProviderUnloaded_Handler,
+		},
+		{
+			MethodName: "OnClientConnect",
+			Handler:    _HookProvider_OnClientConnect_Handler,
+		},
+		{
+			MethodName: "OnClientConnack",
+			Handler:    _HookProvider_OnClientConnack_Handler,
+		},
+		{
+			MethodName: "OnClientConnected",
+			Handler:    _HookProvider_OnClientConnected_Handler,
+		},
+		{
+			MethodName: "OnClientDisconnected",
+			Handler:    _HookProvider_OnClientDisconnected_Handler,
+		},
+		{
+			MethodName: "OnClientAuthenticate",
+			Handler:    _HookProvider_OnClientAuthenticate_Handler,
+		},
+		{
+			MethodName: "OnClientAuthorize",
+			Handler:    _HookProvider_OnClientAuthorize_Handler,
+		},
+		{
+			MethodName: "OnClientSubscribe",
+			Handler:    _HookProvider_OnClientSubscribe_Handler,
+		},
+		{
+			MethodName: "OnClientUnsubscribe",
+			Handler:    _HookProvider_OnClientUnsubscribe_Handler,
+		},
+		{
+			MethodName: "OnSessionCreated",
+			Handler:    _HookProvider_OnSessionCreated_Handler,
+		},
+		{
+			MethodName: "OnSessionSubscribed",
+			Handler:    _HookProvider_OnSessionSubscribed_Handler,
+		},
+		{
+			MethodName: "OnSessionUnsubscribed",
+			Handler:    _HookProvider_OnSessionUnsubscribed_Handler,
+		},
+		{
+			MethodName: "OnSessionResumed",
+			Handler:    _HookProvider_OnSessionResumed_Handler,
+		},
+		{
+			MethodName: "OnSessionDiscarded",
+			Handler:    _HookProvider_OnSessionDiscarded_Handler,
+		},
+		{
+			MethodName: "OnSessionTakenover",
+			Handler:    _HookProvider_OnSessionTakenover_Handler,
+		},
+		{
+			MethodName: "OnSessionTerminated",
+			Handler:    _HookProvider_OnSessionTerminated_Handler,
+		},
+		{
+			MethodName: "OnMessagePublish",
+			Handler:    _HookProvider_OnMessagePublish_Handler,
+		},
+		{
+			MethodName: "OnMessageDelivered",
+			Handler:    _HookProvider_OnMessageDelivered_Handler,
+		},
+		{
+			MethodName: "OnMessageDropped",
+			Handler:    _HookProvider_OnMessageDropped_Handler,
+		},
+		{
+			MethodName: "OnMessageAcked",
+			Handler:    _HookProvider_OnMessageAcked_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "protobuf/exhook.proto",
+}

+ 10 - 0
services/emqx-agent/readme.md

@@ -0,0 +1,10 @@
+## emqx 代理服务
+
+主要作为 emqx 服务的代理,实现emqx hook服务,监听设备接入的事件,维护设备上下线状态,服务启动后订阅所有设备消息并作预处理,转发到规则引擎中。
+
+### 核心功能
+
+* EMQX服务 ExHook 服务,实现了 GPRC
+* 根据hook 事件,完成设备上下线状态维护
+* 订阅设备消息并转发到规则引擎中
+* 实现 easeLink 协议,适配 api provider 服务中的请求,生成协议包转发到设备相应的主题上。

+ 204 - 0
services/emqx-agent/sub_dev.go

@@ -0,0 +1,204 @@
+package main
+
+import (
+	"context"
+	"encoding/json"
+	mqtt "github.com/eclipse/paho.mqtt.golang"
+	"github.com/gogf/gf/os/grpool"
+	"runtime"
+	"runtime/debug"
+	"sparrow/pkg/protocol"
+	"sparrow/pkg/server"
+	"sparrow/services/emqx-agent/client"
+	"strings"
+	"time"
+)
+
+type SubDev interface {
+	SubDevMsg(handle Handle) error
+	PublishToMsgToDev(topic string, payload []byte) error
+}
+
+type ConnectMsg struct {
+	Username       string `json:"username"`
+	Ts             int64  `json:"ts"`
+	Sockport       int    `json:"sockport"`
+	ProtoVer       int    `json:"proto_ver"`
+	ProtoName      string `json:"proto_name"`
+	Keepalive      int    `json:"keepalive"`
+	Ipaddress      string `json:"ipaddress"`
+	ExpiryInterval int    `json:"expiry_interval"`
+	ConnectedAt    int64  `json:"connected_at"`
+	Connack        int    `json:"connack"`
+	Clientid       string `json:"clientid"`
+	Reason         string `json:"reason"`
+	CleanStart     bool   `json:"clean_start"`
+}
+
+type Handle func(ctx context.Context) DevSubHandle
+
+type DevSubHandle interface {
+	Message(topic string, payload []byte) error
+	Connected(status *protocol.DevConnectStatus) error
+	Disconnected(status *protocol.DevConnectStatus) error
+}
+
+type MqttClient struct {
+	client     *client.MqttClient
+	handlePool *grpool.Pool
+}
+
+func (d *MqttClient) PublishToMsgToDev(topic string, payload []byte) error {
+	return d.client.Publish(topic, 1, false, payload)
+}
+
+const (
+	ShareSubTopicPrefix = "$share/sparrow.agent/"
+	TopicConnectStatus  = ShareSubTopicPrefix + "$SYS/brokers/+/clients/#"
+	TopicThing          = ShareSubTopicPrefix + protocol.TopicHeadThing + "/up/#"
+	TopicOta            = ShareSubTopicPrefix + protocol.TopicHeadOta + "/up/#"
+	TopicConfig         = ShareSubTopicPrefix + protocol.TopicHeadConfig + "/up/#"
+	TopicSDKLog         = ShareSubTopicPrefix + protocol.TopicHeadLog + "/up/#"
+	TopicShadow         = ShareSubTopicPrefix + protocol.TopicHeadShadow + "/up/#"
+	TopicGateway        = ShareSubTopicPrefix + protocol.TopicHeadGateway + "/up/#"
+	TopicExt            = ShareSubTopicPrefix + protocol.TopicHeadExt + "/up/#"
+)
+
+func NewSubDev(conf *client.MqttConfig) (SubDev, error) {
+	return newEmqClient(conf)
+}
+
+func newEmqClient(conf *client.MqttConfig) (SubDev, error) {
+	mc, err := client.NewMqttClient(conf)
+	if err != nil {
+		return nil, err
+	}
+	return &MqttClient{
+		client:     mc,
+		handlePool: grpool.New(1000),
+	}, nil
+}
+
+func (d *MqttClient) SubDevMsg(handle Handle) error {
+
+	err := d.subDevMsg(nil, handle)
+	if err != nil {
+		return err
+	}
+	client.SetMqttSetOnConnectHandler(func(cli mqtt.Client) {
+		err := d.subDevMsg(cli, handle)
+		if err != nil {
+			server.Log.Errorf("mqttSetOnConnectHandler.subDevMsg err:%v", err)
+		}
+	})
+	return nil
+}
+
+func (d *MqttClient) subDevMsg(cli mqtt.Client, handle Handle) error {
+	err := d.subscribeWithFunc(cli, TopicConnectStatus, d.subConnectStatus(handle))
+	if err != nil {
+		return err
+	}
+	err = d.subscribeWithFunc(cli, TopicThing, func(ctx context.Context, topic string, payload []byte) error {
+		return handle(ctx).Message(topic, payload)
+	})
+	if err != nil {
+		return err
+	}
+	err = d.subscribeWithFunc(cli, TopicConfig, func(ctx context.Context, topic string, payload []byte) error {
+		return handle(ctx).Message(topic, payload)
+	})
+	if err != nil {
+		return err
+	}
+	err = d.subscribeWithFunc(cli, TopicOta, func(ctx context.Context, topic string, payload []byte) error {
+		return handle(ctx).Message(topic, payload)
+	})
+	if err != nil {
+		return err
+	}
+	err = d.subscribeWithFunc(cli, TopicExt, func(ctx context.Context, topic string, payload []byte) error {
+		return handle(ctx).Message(topic, payload)
+	})
+	if err != nil {
+		return err
+	}
+	err = d.subscribeWithFunc(cli, TopicShadow, func(ctx context.Context, topic string, payload []byte) error {
+		return handle(ctx).Message(topic, payload)
+	})
+
+	if err != nil {
+		return err
+	}
+	err = d.subscribeWithFunc(cli, TopicGateway, func(ctx context.Context, topic string, payload []byte) error {
+		return handle(ctx).Message(topic, payload)
+	})
+	if err != nil {
+		return err
+	}
+	err = d.subscribeWithFunc(cli, TopicSDKLog, func(ctx context.Context, topic string, payload []byte) error {
+		return handle(ctx).Message(topic, payload)
+	})
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (d *MqttClient) subConnectStatus(handle Handle) func(ctx context.Context, topic string, payload []byte) error {
+	return func(ctx context.Context, topic string, payload []byte) error {
+		var (
+			msg ConnectMsg
+			err error
+		)
+		err = json.Unmarshal(payload, &msg)
+		if err != nil {
+			server.Log.Errorf("json.Unmarshal err :%s, topic :%v", err, topic)
+			return err
+		}
+		status := protocol.DevConnectStatus{
+			DeviceCode: msg.Username,
+			DeviceId:   msg.Clientid,
+			ClientIp:   msg.Ipaddress,
+		}
+		if strings.HasSuffix(topic, "/connected") {
+			status.Action = "LOGIN"
+			return handle(ctx).Connected(&status)
+		} else {
+			status.Action = "LOGOUT"
+			status.Reason = msg.Reason
+			return handle(ctx).Disconnected(&status)
+		}
+	}
+}
+
+func (d *MqttClient) subscribeWithFunc(cli mqtt.Client, topic string,
+	handle func(ctx context.Context, topic string, payload []byte) error) error {
+	return d.client.Subscribe(cli, topic, 1, func(c mqtt.Client, message mqtt.Message) {
+		_ = d.handlePool.Add(func() {
+			go func() {
+				ctx, cancel := context.WithTimeout(context.Background(), 50*time.Second)
+				defer cancel()
+				Recover(ctx)
+				err := handle(ctx, message.Topic(), message.Payload())
+				if err != nil {
+					server.Log.Errorf("handle failure err :%s, topic :%v", err, topic)
+				}
+			}()
+		})
+	})
+}
+
+func Recover(ctx context.Context) {
+	if p := recover(); p != nil {
+		HandleThrow(ctx, p)
+	}
+}
+
+func HandleThrow(ctx context.Context, p any) {
+	pc := make([]uintptr, 1)
+	runtime.Callers(3, pc)
+	f := runtime.FuncForPC(pc[0])
+	server.Log.Errorf("HandleThrow|func=%s|error=%#v|stack=%s\n", f, p, string(debug.Stack()))
+	//os.Exit(-1)
+}

+ 82 - 10
services/httpaccess/actions.go

@@ -11,12 +11,9 @@ import (
 	"sparrow/pkg/rpcs"
 	"sparrow/pkg/server"
 	"sparrow/pkg/token"
+	"strconv"
 	"strings"
 
-	"github.com/opentracing/opentracing-go/ext"
-
-	"github.com/opentracing/opentracing-go"
-
 	"github.com/martini-contrib/render"
 )
 
@@ -51,6 +48,16 @@ type DeviceAuthArgs struct {
 	Protocol     string `json:"protocol" binding:"required"`
 }
 
+type AccessAuthArgs struct {
+	UserName string `json:"username"`
+	Password string `json:"password"`
+}
+
+type AccessAuthResp struct {
+	Result      string `json:"result"`       // 可选 "allow" | "deny" | "ignore"
+	IsSuperuser bool   `json:"is_superuser"` // false
+}
+
 // RegisterDevice 设备激活
 func RegisterDevice(args DeviceRegisterArgs, r render.Render) {
 	server.Log.Printf("ACTION RegisterDevice, args:: %v ", args)
@@ -80,17 +87,69 @@ func RegisterDevice(args DeviceRegisterArgs, r render.Render) {
 	return
 }
 
+// DeviceAccessAuth emqx 设备接入认证
+func DeviceAccessAuth(args AccessAuthArgs, r render.Render) {
+	server.Log.Printf("ACTION DeviceAccessAuth, args:: %v", args)
+
+	result := AccessAuthResp{}
+	if args.UserName == "sparrow_test" && args.Password == "sparrow_test" {
+		result.Result = "allow"
+		r.JSON(http.StatusOK, result)
+		return
+	}
+	deviceId, err := ClientIDToDeviceID(args.UserName)
+	if err != nil {
+		server.Log.Errorf("invalid Identify: %s", args.UserName)
+		result.Result = "deny"
+		r.JSON(http.StatusOK, result)
+		return
+	}
+	device := &models.Device{}
+	err = server.RPCCallByName(nil, rpcs.RegistryServerName, "Registry.FindDeviceById", deviceId, device)
+	if err != nil {
+		server.Log.Errorf("device not found %d", deviceId)
+		result.Result = "deny"
+		r.JSON(http.StatusOK, result)
+		return
+	}
+	// parse token
+	token, err := hex.DecodeString(args.Password)
+	if err != nil {
+		server.Log.Errorf("token format error : %v", err)
+		result.Result = "deny"
+		r.JSON(http.StatusOK, result)
+		return
+	}
+	// validate token
+	if err := validateToken(device.RecordId, token); err != nil {
+		server.Log.Errorf("validate token error : %v", err)
+		result.Result = "deny"
+		r.JSON(http.StatusOK, result)
+		return
+	}
+	result.Result = "allow"
+	r.JSON(http.StatusOK, result)
+}
+
+func validateToken(deviceRecordId string, token []byte) error {
+	args := rpcs.ArgsValidateDeviceAccessToken{
+		Id:          deviceRecordId,
+		AccessToken: token,
+	}
+	reply := rpcs.ReplyValidateDeviceAccessToken{}
+	err := server.RPCCallByName(nil, rpcs.DeviceManagerName, "DeviceManager.ValidateDeviceAccessToken", args, &reply)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
 // AuthDevice device auth
 func AuthDevice(args DeviceAuthArgs, r render.Render) {
-	server.Log.Printf("ACTION AuthDevice, args:: %v", args)
 	device := &models.Device{}
 
-	span, ctx := opentracing.StartSpanFromContext(context.Background(), "AuthDevice")
-	defer span.Finish()
-
-	ext.SpanKindRPCClient.Set(span)
 	arg := uint64(args.DeviceId)
-	err := server.RPCCallByName(ctx, rpcs.RegistryServerName, "Registry.FindDeviceById", &arg, device)
+	err := server.RPCCallByName(context.Background(), rpcs.RegistryServerName, "Registry.FindDeviceById", &arg, device)
 	if err != nil {
 		r.JSON(http.StatusOK, renderError(ErrDeviceNotFound, err))
 		return
@@ -117,6 +176,10 @@ func AuthDevice(args DeviceAuthArgs, r render.Render) {
 		hosts, err = server.GetServerHosts(strings.ToUpper(args.Protocol)+"Access", "tcphost")
 	case "coap":
 		hosts, err = server.GetServerHosts(strings.ToUpper(args.Protocol)+"Access", "udphost")
+	case "mqttX": // TODO: 增加配置文件支持
+		hosts = []string{
+			"114.115.251.196:1883",
+		}
 	default:
 		err = errors.New("unsuported protocol: " + args.Protocol)
 	}
@@ -139,3 +202,12 @@ func AuthDevice(args DeviceAuthArgs, r render.Render) {
 	r.JSON(http.StatusOK, result)
 	return
 }
+
+func ClientIDToDeviceID(identify string) (uint64, error) {
+	deviceId, err := strconv.ParseUint(identify, 16, 64)
+	if err != nil {
+		return uint64(0), err
+	}
+
+	return deviceId, nil
+}

+ 2 - 0
services/httpaccess/router.go

@@ -13,4 +13,6 @@ func route(m *martini.ClassicMartini) {
 	// auth device
 	m.Post("/v1/devices/authentication", binding.Json(DeviceAuthArgs{}), AuthDevice)
 
+	m.Post("/v1/external/auth", binding.Json(AccessAuthArgs{}), DeviceAccessAuth)
+
 }

+ 1 - 1
services/mqttaccess/mqtt_provider.go

@@ -94,7 +94,7 @@ func (mp *MQTTProvider) OnDeviceHeartBeat(deviceid string) error {
 }
 func (mp *MQTTProvider) OnDeviceMessage(deviceid, vendorId string, msgtype string, message *gjson.Json) {
 	deviceMessageCount.WithLabelValues(deviceid).Inc()
-	server.Log.Infof("device {%v} message {%v} : %s", deviceid, msgtype, message.MustToJsonString())
+	server.Log.Debugf("device {%v} message {%v} : %s", deviceid, msgtype, message.MustToJsonString())
 	switch msgtype {
 	case "s":
 		act := klink.PacketAction(message.GetString("action"))

+ 9 - 9
tests/device/device.go

@@ -15,7 +15,7 @@ import (
 	"sparrow/pkg/tlv"
 	"time"
 
-	MQTT "git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git"
+	MQTT "github.com/eclipse/paho.mqtt.golang"
 )
 
 const (
@@ -166,7 +166,7 @@ func (d *Device) DoLogin() error {
 	return nil
 }
 
-func (d *Device) reportStatus(client *MQTT.Client) {
+func (d *Device) reportStatus(client MQTT.Client) {
 	for {
 		time.Sleep(2 * time.Second)
 		rand.Seed(time.Now().UnixNano())
@@ -190,7 +190,7 @@ func (d *Device) reportStatus(client *MQTT.Client) {
 	}
 
 }
-func (d *Device) reportStatus2(client *MQTT.Client) {
+func (d *Device) reportStatus2(client MQTT.Client) {
 	for {
 		time.Sleep(2 * time.Second)
 		rand.Seed(time.Now().UnixNano())
@@ -265,7 +265,7 @@ func (d *Device) coapReportStatus(conn *net.UDPConn) {
 	}
 }
 
-func (d *Device) reportEvent(client *MQTT.Client) {
+func (d *Device) reportEvent(client MQTT.Client) {
 	for {
 		time.Sleep(2 * time.Second)
 
@@ -288,7 +288,7 @@ func (d *Device) reportEvent(client *MQTT.Client) {
 	}
 }
 
-func (d *Device) statusHandler(client *MQTT.Client, msg MQTT.Message) {
+func (d *Device) statusHandler(client MQTT.Client, msg MQTT.Message) {
 	status := protocol.Data{}
 
 	err := status.UnMarshal(msg.Payload())
@@ -307,7 +307,7 @@ func (d *Device) statusHandler(client *MQTT.Client, msg MQTT.Message) {
 }
 
 // 子设备上线
-func (d *Device) subDeviceLogin(client *MQTT.Client) {
+func (d *Device) subDeviceLogin(client MQTT.Client) {
 	for {
 		dd := &klink.DevLogin{
 			Action:      "devLogin",
@@ -326,7 +326,7 @@ func (d *Device) subDeviceLogin(client *MQTT.Client) {
 }
 
 // 子设备上线
-func (d *Device) deviceNetConfig(client *MQTT.Client) {
+func (d *Device) deviceNetConfig(client MQTT.Client) {
 	j := `{
   "action": "devNetConfig",
   "timestamp": 12312312,
@@ -338,7 +338,7 @@ func (d *Device) deviceNetConfig(client *MQTT.Client) {
 
 }
 
-func (d *Device) commandHandler(client *MQTT.Client, msg MQTT.Message) {
+func (d *Device) commandHandler(client MQTT.Client, msg MQTT.Message) {
 	j, err := gjson.DecodeToJson(msg.Payload())
 	if err != nil {
 		panic("错误的报文格式")
@@ -346,7 +346,7 @@ func (d *Device) commandHandler(client *MQTT.Client, msg MQTT.Message) {
 	fmt.Printf("%v", j.MustToJsonString())
 }
 
-func (d *Device) messageHandler(client *MQTT.Client, msg MQTT.Message) {
+func (d *Device) messageHandler(client MQTT.Client, msg MQTT.Message) {
 	fmt.Printf("TOPIC: %s\n", msg.Topic())
 	fmt.Printf("MSG: %x\n", msg.Payload())
 	msgtype := msg.Topic()

BIN
vendor/.DS_Store


+ 0 - 69
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/CONTRIBUTING.md

@@ -1,69 +0,0 @@
-Contributing to Paho
-====================
-
-Thanks for your interest in this project.
-
-Project description:
---------------------
-
-The Paho project has been created to provide scalable open-source implementations of open and standard messaging protocols aimed at new, existing, and emerging applications for Machine-to-Machine (M2M) and Internet of Things (IoT).
-Paho reflects the inherent physical and cost constraints of device connectivity. Its objectives include effective levels of decoupling between devices and applications, designed to keep markets open and encourage the rapid growth of scalable Web and Enterprise middleware and applications. Paho is being kicked off with MQTT publish/subscribe client implementations for use on embedded platforms, along with corresponding server support as determined by the community.
-
-- https://projects.eclipse.org/projects/technology.paho
-
-Developer resources:
---------------------
-
-Information regarding source code management, builds, coding standards, and more.
-
-- https://projects.eclipse.org/projects/technology.paho/developer
-
-Contributor License Agreement:
-------------------------------
-
-Before your contribution can be accepted by the project, you need to create and electronically sign the Eclipse Foundation Contributor License Agreement (CLA).
-
-- http://www.eclipse.org/legal/CLA.php
-
-Contributing Code:
-------------------
-
-The Go client uses git with Gerrit for code review, use the following URLs for Gerrit access;
-
-ssh://<username>@git.eclipse.org:29418/paho/org.eclipse.paho.mqtt.golang
-
-Configure a remote called review to push your changes to;
-
-git config remote.review.url ssh://<username>@git.eclipse.org:29418/paho/org.eclipse.paho.mqtt.golang
-git config remote.review.push HEAD:refs/for/<branch>
-
-When you have made and committed a change you can push it to Gerrit for review with;
-
-git push review
-
-See https://wiki.eclipse.org/Gerrit for more details on how Gerrit is used in Eclipse, https://wiki.eclipse.org/Gerrit#Gerrit_Code_Review_Cheatsheet has some particularly useful information.
-
-Git commit messages should follow the style described here;
-
-http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
-
-Contact:
---------
-
-Contact the project developers via the project's "dev" list.
-
-- https://dev.eclipse.org/mailman/listinfo/paho-dev
-
-Search for bugs:
-----------------
-
-This project uses Bugzilla to track ongoing development and issues.
-
-- https://bugs.eclipse.org/bugs/buglist.cgi?product=Paho&component=MQTT-Go
-
-Create a new bug:
------------------
-
-Be sure to search for existing bugs before you create another one. Remember that contributions are always welcome!
-
-- https://bugs.eclipse.org/bugs/enter_bug.cgi?product=Paho

+ 0 - 15
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/DISTRIBUTION

@@ -1,15 +0,0 @@
-
-
-Eclipse Distribution License - v 1.0
-
-Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors.
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
-    Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-    Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-    Neither the name of the Eclipse Foundation, 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.

+ 0 - 87
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/LICENSE

@@ -1,87 +0,0 @@
-Eclipse Public License - v 1.0
-
-THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-1. DEFINITIONS
-
-"Contribution" means:
-
-a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and
-
-b) in the case of each subsequent Contributor:
-
-i) changes to the Program, and
-
-ii) additions to the Program;
-
-where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.
-
-"Contributor" means any person or entity that distributes the Program.
-
-"Licensed Patents" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.
-
-"Program" means the Contributions distributed in accordance with this Agreement.
-
-"Recipient" means anyone who receives the Program under this Agreement, including all Contributors.
-
-2. GRANT OF RIGHTS
-
-a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
-
-b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
-
-c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
-
-d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.
-
-3. REQUIREMENTS
-
-A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:
-
-a) it complies with the terms and conditions of this Agreement; and
-
-b) its license agreement:
-
-i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;
-
-ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;
-
-iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and
-
-iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.
-
-When the Program is made available in source code form:
-
-a) it must be made available under this Agreement; and
-
-b) a copy of this Agreement must be included with each copy of the Program.
-
-Contributors may not remove or alter any copyright notices contained within the Program.
-
-Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.
-
-4. COMMERCIAL DISTRIBUTION
-
-Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.
-
-For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.
-
-5. NO WARRANTY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED 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. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.
-
-6. DISCLAIMER OF LIABILITY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-7. GENERAL
-
-If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
-
-If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.
-
-Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved.
-
-This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.

+ 0 - 62
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/README.md

@@ -1,62 +0,0 @@
-Eclipse Paho MQTT Go client
-===========================
-
-
-This repository contains the source code for the [Eclipse Paho](http://eclipse.org/paho) MQTT Go client library. 
-
-This code builds a library which enable applications to connect to an [MQTT](http://mqtt.org) broker to publish messages, and to subscribe to topics and receive published messages.
-
-This library supports a fully asynchronous mode of operation.
-
-
-Installation and Build
-----------------------
-
-This client is designed to work with the standard Go tools, so installation is as easy as:
-
-```
-go get git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git
-```
-
-The client depends on Google's [websockets](http://godoc.org/code.google.com/p/go.net/websocket) package, 
-also easily installed with the command:
-
-```
-go get code.google.com/p/go.net/websocket
-```
-
-
-Usage and API
--------------
-
-Detailed API documentation is available by using to godoc tool, or can be browsed online
-using the [godoc.org](http://godoc.org/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git) service.
-
-Make use of the library by importing it in your Go client source code. For example,
-```
-import MQTT "git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git"
-```
-
-Samples are available in the `/samples` directory for reference.
-
-
-Runtime tracing
----------------
-
-Tracing is enabled by assigning logs (from the Go log package) to the logging endpoints, ERROR, CRITICAL, WARN and DEBUG
-
-
-Reporting bugs
---------------
-
-Please report bugs under the "MQTT-Go" Component in [Eclipse Bugzilla](http://bugs.eclipse.org/bugs/) for the Paho Technology project. This is a very new library as of Q1 2014, so there are sure to be bugs.
-
-
-More information
-----------------
-
-Discussion of the Paho clients takes place on the [Eclipse paho-dev mailing list](https://dev.eclipse.org/mailman/listinfo/paho-dev).
-
-General questions about the MQTT protocol are discussed in the [MQTT Google Group](https://groups.google.com/forum/?hl=en-US&fromgroups#!forum/mqtt).
-
-There is much more information available via the [MQTT community site](http://mqtt.org).

+ 0 - 41
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/about.html

@@ -1,41 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"><head>
-<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
-<title>About</title>
-</head>
-<body lang="EN-US">
-<h2>About This Content</h2>
- 
-<p><em>December 9, 2013</em></p>	
-<h3>License</h3>
-
-<p>The Eclipse Foundation makes available all content in this plug-in ("Content").  Unless otherwise 
-indicated below, the Content is provided to you under the terms and conditions of the
-Eclipse Public License Version 1.0 ("EPL") and Eclipse Distribution License Version 1.0 ("EDL").
-A copy of the EPL is available at 
-<a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a> 
-and a copy of the EDL is available at 
-<a href="http://www.eclipse.org/org/documents/edl-v10.php">http://www.eclipse.org/org/documents/edl-v10.php</a>. 
-For purposes of the EPL, "Program" will mean the Content.</p>
-
-<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
-being redistributed by another party ("Redistributor") and different terms and conditions may
-apply to your use of any object code in the Content.  Check the Redistributor's license that was 
-provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
-indicated below, the terms and conditions of the EPL still apply to any source code in the Content
-and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
-
-		
-		<h3>Third Party Content</h3>
-		<p>The Content includes items that have been sourced from third parties as set out below. If you 
-		did not receive this Content directly from the Eclipse Foundation, the following is provided 
-		for informational purposes only, and you should look to the Redistributor's license for 
-		terms and conditions of use.</p>
-		<p><em>
-		<strong>None</strong> <br><br>
-		<br><br> 
-		</em></p>
-
-
-
-</body></html>

+ 0 - 521
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/client.go

@@ -1,521 +0,0 @@
-/*
- * Copyright (c) 2013 IBM Corp.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Seth Hoenig
- *    Allan Stockdill-Mander
- *    Mike Robertson
- */
-
-// Package mqtt provides an MQTT v3.1.1 client library.
-package mqtt
-
-import (
-	"errors"
-	"fmt"
-	"git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets"
-	"net"
-	"sync"
-	"time"
-)
-
-// ClientInt is the interface definition for a Client as used by this
-// library, the interface is primarily to allow mocking tests.
-type ClientInt interface {
-	IsConnected() bool
-	Connect() Token
-	Disconnect(uint)
-	disconnect()
-	Publish(string, byte, bool, interface{}) Token
-	Subscribe(string, byte, MessageHandler) Token
-	SubscribeMultiple(map[string]byte, MessageHandler) Token
-	Unsubscribe(...string) Token
-}
-
-// Client is an MQTT v3.1.1 client for communicating
-// with an MQTT server using non-blocking methods that allow work
-// to be done in the background.
-// An application may connect to an MQTT server using:
-//   A plain TCP socket
-//   A secure SSL/TLS socket
-//   A websocket
-// To enable ensured message delivery at Quality of Service (QoS) levels
-// described in the MQTT spec, a message persistence mechanism must be
-// used. This is done by providing a type which implements the Store
-// interface. For convenience, FileStore and MemoryStore are provided
-// implementations that should be sufficient for most use cases. More
-// information can be found in their respective documentation.
-// Numerous connection options may be specified by configuring a
-// and then supplying a ClientOptions type.
-type Client struct {
-	sync.RWMutex
-	messageIds
-	conn            net.Conn
-	ibound          chan packets.ControlPacket
-	obound          chan *PacketAndToken
-	oboundP         chan *PacketAndToken
-	msgRouter       *router
-	stopRouter      chan bool
-	incomingPubChan chan *packets.PublishPacket
-	errors          chan error
-	stop            chan struct{}
-	persist         Store
-	options         ClientOptions
-	lastContact     lastcontact
-	pingOutstanding bool
-	connected       bool
-	workers         sync.WaitGroup
-}
-
-// NewClient will create an MQTT v3.1.1 client with all of the options specified
-// in the provided ClientOptions. The client must have the Start method called
-// on it before it may be used. This is to make sure resources (such as a net
-// connection) are created before the application is actually ready.
-func NewClient(o *ClientOptions) *Client {
-	c := &Client{}
-	c.options = *o
-
-	if c.options.Store == nil {
-		c.options.Store = NewMemoryStore()
-	}
-	switch c.options.ProtocolVersion {
-	case 3, 4:
-		c.options.protocolVersionExplicit = true
-	default:
-		c.options.ProtocolVersion = 4
-		c.options.protocolVersionExplicit = false
-	}
-	c.persist = c.options.Store
-	c.connected = false
-	c.messageIds = messageIds{index: make(map[uint16]Token)}
-	c.msgRouter, c.stopRouter = newRouter()
-	c.msgRouter.setDefaultHandler(c.options.DefaultPublishHander)
-	return c
-}
-
-// IsConnected returns a bool signifying whether
-// the client is connected or not.
-func (c *Client) IsConnected() bool {
-	c.RLock()
-	defer c.RUnlock()
-	return c.connected
-}
-
-func (c *Client) setConnected(status bool) {
-	c.Lock()
-	defer c.Unlock()
-	c.connected = status
-}
-
-//ErrNotConnected is the error returned from function calls that are
-//made when the client is not connected to a broker
-var ErrNotConnected = errors.New("Not Connected")
-
-// Connect will create a connection to the message broker
-// If clean session is false, then a slice will
-// be returned containing Receipts for all messages
-// that were in-flight at the last disconnect.
-// If clean session is true, then any existing client
-// state will be removed.
-func (c *Client) Connect() Token {
-	var err error
-	t := newToken(packets.Connect).(*ConnectToken)
-	DEBUG.Println(CLI, "Connect()")
-
-	go func() {
-		var rc byte
-		cm := newConnectMsgFromOptions(&c.options)
-
-		for _, broker := range c.options.Servers {
-		CONN:
-			DEBUG.Println(CLI, "about to write new connect msg")
-			c.conn, err = openConnection(broker, &c.options.TLSConfig, c.options.ConnectTimeout)
-			if err == nil {
-				DEBUG.Println(CLI, "socket connected to broker")
-				switch c.options.ProtocolVersion {
-				case 3:
-					DEBUG.Println(CLI, "Using MQTT 3.1 protocol")
-					cm.ProtocolName = "MQIsdp"
-					cm.ProtocolVersion = 3
-				default:
-					DEBUG.Println(CLI, "Using MQTT 3.1.1 protocol")
-					c.options.ProtocolVersion = 4
-					cm.ProtocolName = "MQTT"
-					cm.ProtocolVersion = 4
-				}
-				cm.Write(c.conn)
-
-				rc = c.connect()
-				if rc != packets.Accepted {
-					c.conn.Close()
-					c.conn = nil
-					//if the protocol version was explicitly set don't do any fallback
-					if c.options.protocolVersionExplicit {
-						ERROR.Println(CLI, "Connecting to", broker, "CONNACK was not CONN_ACCEPTED, but rather", packets.ConnackReturnCodes[rc])
-						continue
-					}
-					if c.options.ProtocolVersion == 4 {
-						DEBUG.Println(CLI, "Trying reconnect using MQTT 3.1 protocol")
-						c.options.ProtocolVersion = 3
-						goto CONN
-					}
-				}
-				break
-			} else {
-				ERROR.Println(CLI, err.Error())
-				WARN.Println(CLI, "failed to connect to broker, trying next")
-				rc = packets.ErrNetworkError
-			}
-		}
-
-		if c.conn == nil {
-			ERROR.Println(CLI, "Failed to connect to a broker")
-			t.returnCode = rc
-			if rc != packets.ErrNetworkError {
-				t.err = packets.ConnErrors[rc]
-			} else {
-				t.err = fmt.Errorf("%s : %s", packets.ConnErrors[rc], err)
-			}
-			t.flowComplete()
-			return
-		}
-
-		c.lastContact.update()
-		c.persist.Open()
-
-		c.obound = make(chan *PacketAndToken, 100)
-		c.oboundP = make(chan *PacketAndToken, 100)
-		c.ibound = make(chan packets.ControlPacket)
-		c.errors = make(chan error)
-		c.stop = make(chan struct{})
-
-		c.incomingPubChan = make(chan *packets.PublishPacket, 100)
-		c.msgRouter.matchAndDispatch(c.incomingPubChan, c.options.Order, c)
-
-		c.workers.Add(1)
-		go outgoing(c)
-		go alllogic(c)
-
-		c.connected = true
-		DEBUG.Println(CLI, "client is connected")
-		if c.options.OnConnect != nil {
-			go c.options.OnConnect(c)
-		}
-
-		if c.options.KeepAlive != 0 {
-			c.workers.Add(1)
-			go keepalive(c)
-		}
-
-		// Take care of any messages in the store
-		//var leftovers []Receipt
-		if c.options.CleanSession == false {
-			//leftovers = c.resume()
-		} else {
-			c.persist.Reset()
-		}
-
-		// Do not start incoming until resume has completed
-		c.workers.Add(1)
-		go incoming(c)
-
-		DEBUG.Println(CLI, "exit startClient")
-		t.flowComplete()
-	}()
-	return t
-}
-
-// internal function used to reconnect the client when it loses its connection
-func (c *Client) reconnect() {
-	DEBUG.Println(CLI, "enter reconnect")
-	var rc byte = 1
-	var sleep uint = 1
-	var err error
-
-	for rc != 0 {
-		cm := newConnectMsgFromOptions(&c.options)
-
-		for _, broker := range c.options.Servers {
-		CONN:
-			DEBUG.Println(CLI, "about to write new connect msg")
-			c.conn, err = openConnection(broker, &c.options.TLSConfig, c.options.ConnectTimeout)
-			if err == nil {
-				DEBUG.Println(CLI, "socket connected to broker")
-				switch c.options.ProtocolVersion {
-				case 3:
-					DEBUG.Println(CLI, "Using MQTT 3.1 protocol")
-					cm.ProtocolName = "MQIsdp"
-					cm.ProtocolVersion = 3
-				default:
-					DEBUG.Println(CLI, "Using MQTT 3.1.1 protocol")
-					c.options.ProtocolVersion = 4
-					cm.ProtocolName = "MQTT"
-					cm.ProtocolVersion = 4
-				}
-				cm.Write(c.conn)
-
-				rc = c.connect()
-				if rc != packets.Accepted {
-					c.conn.Close()
-					c.conn = nil
-					//if the protocol version was explicitly set don't do any fallback
-					if c.options.protocolVersionExplicit {
-						ERROR.Println(CLI, "Connecting to", broker, "CONNACK was not Accepted, but rather", packets.ConnackReturnCodes[rc])
-						continue
-					}
-					if c.options.ProtocolVersion == 4 {
-						DEBUG.Println(CLI, "Trying reconnect using MQTT 3.1 protocol")
-						c.options.ProtocolVersion = 3
-						goto CONN
-					}
-				}
-				break
-			} else {
-				ERROR.Println(CLI, err.Error())
-				WARN.Println(CLI, "failed to connect to broker, trying next")
-				rc = packets.ErrNetworkError
-			}
-		}
-		if rc != 0 {
-			DEBUG.Println(CLI, "Reconnect failed, sleeping for", sleep, "seconds")
-			time.Sleep(time.Duration(sleep) * time.Second)
-			if sleep <= uint(c.options.MaxReconnectInterval.Seconds()) {
-				sleep *= 2
-			}
-		}
-	}
-
-	c.lastContact.update()
-	c.stop = make(chan struct{})
-
-	c.workers.Add(1)
-	go outgoing(c)
-	go alllogic(c)
-
-	c.setConnected(true)
-	DEBUG.Println(CLI, "client is reconnected")
-	if c.options.OnConnect != nil {
-		go c.options.OnConnect(c)
-	}
-
-	if c.options.KeepAlive != 0 {
-		c.workers.Add(1)
-		go keepalive(c)
-	}
-	c.workers.Add(1)
-	go incoming(c)
-}
-
-// This function is only used for receiving a connack
-// when the connection is first started.
-// This prevents receiving incoming data while resume
-// is in progress if clean session is false.
-func (c *Client) connect() byte {
-	DEBUG.Println(NET, "connect started")
-
-	ca, err := packets.ReadPacket(c.conn)
-	if err != nil {
-		ERROR.Println(NET, "connect got error", err)
-		return packets.ErrNetworkError
-	}
-	if ca == nil {
-		ERROR.Println(NET, "received nil packet")
-		return packets.ErrNetworkError
-	}
-
-	msg, ok := ca.(*packets.ConnackPacket)
-	if !ok {
-		ERROR.Println(NET, "received msg that was not CONNACK")
-		return packets.ErrNetworkError
-	}
-
-	DEBUG.Println(NET, "received connack")
-	return msg.ReturnCode
-}
-
-// Disconnect will end the connection with the server, but not before waiting
-// the specified number of milliseconds to wait for existing work to be
-// completed.
-func (c *Client) Disconnect(quiesce uint) {
-	if !c.IsConnected() {
-		WARN.Println(CLI, "already disconnected")
-		return
-	}
-	DEBUG.Println(CLI, "disconnecting")
-	c.setConnected(false)
-
-	dm := packets.NewControlPacket(packets.Disconnect).(*packets.DisconnectPacket)
-	dt := newToken(packets.Disconnect)
-	c.oboundP <- &PacketAndToken{p: dm, t: dt}
-
-	// wait for work to finish, or quiesce time consumed
-	dt.WaitTimeout(time.Duration(quiesce) * time.Millisecond)
-	c.disconnect()
-}
-
-// ForceDisconnect will end the connection with the mqtt broker immediately.
-func (c *Client) forceDisconnect() {
-	if !c.IsConnected() {
-		WARN.Println(CLI, "already disconnected")
-		return
-	}
-	c.setConnected(false)
-	c.conn.Close()
-	DEBUG.Println(CLI, "forcefully disconnecting")
-	c.disconnect()
-}
-
-func (c *Client) internalConnLost(err error) {
-	close(c.stop)
-	c.conn.Close()
-	c.workers.Wait()
-	if c.IsConnected() {
-		if c.options.OnConnectionLost != nil {
-			go c.options.OnConnectionLost(c, err)
-		}
-		if c.options.AutoReconnect {
-			go c.reconnect()
-		} else {
-			c.setConnected(false)
-		}
-	}
-}
-
-func (c *Client) disconnect() {
-	select {
-	case <-c.stop:
-		//someone else has already closed the channel, must be error
-	default:
-		close(c.stop)
-	}
-	c.conn.Close()
-	c.workers.Wait()
-	close(c.stopRouter)
-	DEBUG.Println(CLI, "disconnected")
-	c.persist.Close()
-}
-
-// Publish will publish a message with the specified QoS
-// and content to the specified topic.
-// Returns a read only channel used to track
-// the delivery of the message.
-func (c *Client) Publish(topic string, qos byte, retained bool, payload interface{}) Token {
-	token := newToken(packets.Publish).(*PublishToken)
-	DEBUG.Println(CLI, "enter Publish")
-	if !c.IsConnected() {
-		token.err = ErrNotConnected
-		token.flowComplete()
-		return token
-	}
-	pub := packets.NewControlPacket(packets.Publish).(*packets.PublishPacket)
-	pub.Qos = qos
-	pub.TopicName = topic
-	pub.Retain = retained
-	switch payload.(type) {
-	case string:
-		pub.Payload = []byte(payload.(string))
-	case []byte:
-		pub.Payload = payload.([]byte)
-	default:
-		token.err = errors.New("Unknown payload type")
-		token.flowComplete()
-		return token
-	}
-
-	DEBUG.Println(CLI, "sending publish message, topic:", topic)
-	c.obound <- &PacketAndToken{p: pub, t: token}
-	return token
-}
-
-// Subscribe starts a new subscription. Provide a MessageHandler to be executed when
-// a message is published on the topic provided.
-func (c *Client) Subscribe(topic string, qos byte, callback MessageHandler) Token {
-	token := newToken(packets.Subscribe).(*SubscribeToken)
-	DEBUG.Println(CLI, "enter Subscribe")
-	if !c.IsConnected() {
-		token.err = ErrNotConnected
-		token.flowComplete()
-		return token
-	}
-	sub := packets.NewControlPacket(packets.Subscribe).(*packets.SubscribePacket)
-	if err := validateTopicAndQos(topic, qos); err != nil {
-		token.err = err
-		return token
-	}
-	sub.Topics = append(sub.Topics, topic)
-	sub.Qoss = append(sub.Qoss, qos)
-	DEBUG.Println(sub.String())
-
-	if callback != nil {
-		c.msgRouter.addRoute(topic, callback)
-	}
-
-	token.subs = append(token.subs, topic)
-	c.oboundP <- &PacketAndToken{p: sub, t: token}
-	DEBUG.Println(CLI, "exit Subscribe")
-	return token
-}
-
-// SubscribeMultiple starts a new subscription for multiple topics. Provide a MessageHandler to
-// be executed when a message is published on one of the topics provided.
-func (c *Client) SubscribeMultiple(filters map[string]byte, callback MessageHandler) Token {
-	var err error
-	token := newToken(packets.Subscribe).(*SubscribeToken)
-	DEBUG.Println(CLI, "enter SubscribeMultiple")
-	if !c.IsConnected() {
-		token.err = ErrNotConnected
-		token.flowComplete()
-		return token
-	}
-	sub := packets.NewControlPacket(packets.Subscribe).(*packets.SubscribePacket)
-	if sub.Topics, sub.Qoss, err = validateSubscribeMap(filters); err != nil {
-		token.err = err
-		return token
-	}
-
-	if callback != nil {
-		for topic := range filters {
-			c.msgRouter.addRoute(topic, callback)
-		}
-	}
-	token.subs = make([]string, len(sub.Topics))
-	copy(token.subs, sub.Topics)
-	c.oboundP <- &PacketAndToken{p: sub, t: token}
-	DEBUG.Println(CLI, "exit SubscribeMultiple")
-	return token
-}
-
-// Unsubscribe will end the subscription from each of the topics provided.
-// Messages published to those topics from other clients will no longer be
-// received.
-func (c *Client) Unsubscribe(topics ...string) Token {
-	token := newToken(packets.Unsubscribe).(*UnsubscribeToken)
-	DEBUG.Println(CLI, "enter Unsubscribe")
-	if !c.IsConnected() {
-		token.err = ErrNotConnected
-		token.flowComplete()
-		return token
-	}
-	unsub := packets.NewControlPacket(packets.Unsubscribe).(*packets.UnsubscribePacket)
-	unsub.Topics = make([]string, len(topics))
-	copy(unsub.Topics, topics)
-
-	c.oboundP <- &PacketAndToken{p: unsub, t: token}
-	for _, topic := range topics {
-		c.msgRouter.deleteRoute(topic)
-	}
-
-	DEBUG.Println(CLI, "exit Unsubscribe")
-	return token
-}
-
-//DefaultConnectionLostHandler is a definition of a function that simply
-//reports to the DEBUG log the reason for the client losing a connection.
-func DefaultConnectionLostHandler(client *Client, reason error) {
-	DEBUG.Println("Connection lost:", reason.Error())
-}

+ 0 - 31
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/components.go

@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2013 IBM Corp.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Seth Hoenig
- *    Allan Stockdill-Mander
- *    Mike Robertson
- */
-
-package mqtt
-
-type component string
-
-// Component names for debug output
-const (
-	NET component = "[net]     "
-	PNG component = "[pinger]  "
-	CLI component = "[client]  "
-	DEC component = "[decode]  "
-	MES component = "[message] "
-	STR component = "[store]   "
-	MID component = "[msgids]  "
-	TST component = "[test]    "
-	STA component = "[state]   "
-	ERR component = "[error]   "
-)

+ 0 - 70
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/epl-v10

@@ -1,70 +0,0 @@
-Eclipse Public License - v 1.0
-
-THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-1. DEFINITIONS
-
-"Contribution" means:
-
-a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and
-b) in the case of each subsequent Contributor:
-i) changes to the Program, and
-ii) additions to the Program;
-where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.
-"Contributor" means any person or entity that distributes the Program.
-
-"Licensed Patents" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.
-
-"Program" means the Contributions distributed in accordance with this Agreement.
-
-"Recipient" means anyone who receives the Program under this Agreement, including all Contributors.
-
-2. GRANT OF RIGHTS
-
-a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
-b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
-c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
-d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.
-3. REQUIREMENTS
-
-A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:
-
-a) it complies with the terms and conditions of this Agreement; and
-b) its license agreement:
-i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;
-ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;
-iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and
-iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.
-When the Program is made available in source code form:
-
-a) it must be made available under this Agreement; and
-b) a copy of this Agreement must be included with each copy of the Program.
-Contributors may not remove or alter any copyright notices contained within the Program.
-
-Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.
-
-4. COMMERCIAL DISTRIBUTION
-
-Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.
-
-For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.
-
-5. NO WARRANTY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED 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. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.
-
-6. DISCLAIMER OF LIABILITY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-7. GENERAL
-
-If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
-
-If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.
-
-Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved.
-
-This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.

+ 0 - 258
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/filestore.go

@@ -1,258 +0,0 @@
-/*
- * Copyright (c) 2013 IBM Corp.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Seth Hoenig
- *    Allan Stockdill-Mander
- *    Mike Robertson
- */
-
-package mqtt
-
-import (
-	"git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets"
-	"io"
-	"io/ioutil"
-	"os"
-	"path"
-	"sync"
-)
-
-const (
-	msgExt = ".msg"
-	bkpExt = ".bkp"
-)
-
-// FileStore implements the store interface using the filesystem to provide
-// true persistence, even across client failure. This is designed to use a
-// single directory per running client. If you are running multiple clients
-// on the same filesystem, you will need to be careful to specify unique
-// store directories for each.
-type FileStore struct {
-	sync.RWMutex
-	directory string
-	opened    bool
-}
-
-// NewFileStore will create a new FileStore which stores its messages in the
-// directory provided.
-func NewFileStore(directory string) *FileStore {
-	store := &FileStore{
-		directory: directory,
-		opened:    false,
-	}
-	return store
-}
-
-// Open will allow the FileStore to be used.
-func (store *FileStore) Open() {
-	store.Lock()
-	defer store.Unlock()
-	// if no store directory was specified in ClientOpts, by default use the
-	// current working directory
-	if store.directory == "" {
-		store.directory, _ = os.Getwd()
-	}
-
-	// if store dir exists, great, otherwise, create it
-	if !exists(store.directory) {
-		perms := os.FileMode(0770)
-		merr := os.MkdirAll(store.directory, perms)
-		chkerr(merr)
-	}
-	store.opened = true
-	DEBUG.Println(STR, "store is opened at", store.directory)
-}
-
-// Close will disallow the FileStore from being used.
-func (store *FileStore) Close() {
-	store.Lock()
-	defer store.Unlock()
-	store.opened = false
-	WARN.Println(STR, "store is not open")
-}
-
-// Put will put a message into the store, associated with the provided
-// key value.
-func (store *FileStore) Put(key string, m packets.ControlPacket) {
-	store.Lock()
-	defer store.Unlock()
-	chkcond(store.opened)
-	full := fullpath(store.directory, key)
-	if exists(full) {
-		backup(store.directory, key) // make a copy of what already exists
-		defer unbackup(store.directory, key)
-	}
-	write(store.directory, key, m)
-	chkcond(exists(full))
-}
-
-// Get will retrieve a message from the store, the one associated with
-// the provided key value.
-func (store *FileStore) Get(key string) packets.ControlPacket {
-	store.RLock()
-	defer store.RUnlock()
-	chkcond(store.opened)
-	filepath := fullpath(store.directory, key)
-	if !exists(filepath) {
-		return nil
-	}
-	mfile, oerr := os.Open(filepath)
-	chkerr(oerr)
-	//all, rerr := ioutil.ReadAll(mfile)
-	//chkerr(rerr)
-	msg, rerr := packets.ReadPacket(mfile)
-	chkerr(rerr)
-	cerr := mfile.Close()
-	chkerr(cerr)
-	return msg
-}
-
-// All will provide a list of all of the keys associated with messages
-// currenly residing in the FileStore.
-func (store *FileStore) All() []string {
-	store.RLock()
-	defer store.RUnlock()
-	return store.all()
-}
-
-// Del will remove the persisted message associated with the provided
-// key from the FileStore.
-func (store *FileStore) Del(key string) {
-	store.Lock()
-	defer store.Unlock()
-	store.del(key)
-}
-
-// Reset will remove all persisted messages from the FileStore.
-func (store *FileStore) Reset() {
-	store.Lock()
-	defer store.Unlock()
-	WARN.Println(STR, "FileStore Reset")
-	for _, key := range store.all() {
-		store.del(key)
-	}
-}
-
-// lockless
-func (store *FileStore) all() []string {
-	chkcond(store.opened)
-	keys := []string{}
-	files, rderr := ioutil.ReadDir(store.directory)
-	chkerr(rderr)
-	for _, f := range files {
-		DEBUG.Println(STR, "file in All():", f.Name())
-		key := f.Name()[0 : len(f.Name())-4] // remove file extension
-		keys = append(keys, key)
-	}
-	return keys
-}
-
-// lockless
-func (store *FileStore) del(key string) {
-	chkcond(store.opened)
-	DEBUG.Println(STR, "store del filepath:", store.directory)
-	DEBUG.Println(STR, "store delete key:", key)
-	filepath := fullpath(store.directory, key)
-	DEBUG.Println(STR, "path of deletion:", filepath)
-	if !exists(filepath) {
-		WARN.Println(STR, "store could not delete key:", key)
-		return
-	}
-	rerr := os.Remove(filepath)
-	chkerr(rerr)
-	DEBUG.Println(STR, "del msg:", key)
-	chkcond(!exists(filepath))
-}
-
-func fullpath(store string, key string) string {
-	p := path.Join(store, key+msgExt)
-	return p
-}
-
-func bkppath(store string, key string) string {
-	p := path.Join(store, key+bkpExt)
-	return p
-}
-
-// create file called "X.[messageid].msg" located in the store
-// the contents of the file is the bytes of the message
-// if a message with m's message id already exists, it will
-// be overwritten
-// X will be 'i' for inbound messages, and O for outbound messages
-func write(store, key string, m packets.ControlPacket) {
-	filepath := fullpath(store, key)
-	f, err := os.Create(filepath)
-	chkerr(err)
-	werr := m.Write(f)
-	chkerr(werr)
-	cerr := f.Close()
-	chkerr(cerr)
-}
-
-func exists(file string) bool {
-	if _, err := os.Stat(file); err != nil {
-		if os.IsNotExist(err) {
-			return false
-		}
-		chkerr(err)
-	}
-	return true
-}
-
-func backup(store, key string) {
-	bkpp := bkppath(store, key)
-	fulp := fullpath(store, key)
-	backup, err := os.Create(bkpp)
-	chkerr(err)
-	mfile, oerr := os.Open(fulp)
-	chkerr(oerr)
-	_, cerr := io.Copy(backup, mfile)
-	chkerr(cerr)
-	clberr := backup.Close()
-	chkerr(clberr)
-	clmerr := mfile.Close()
-	chkerr(clmerr)
-}
-
-// Identify .bkp files in the store and turn them into .msg files,
-// whether or not it overwrites an existing file. This is safe because
-// I'm copying the Paho Java client and they say it is.
-func restore(store string) {
-	files, rderr := ioutil.ReadDir(store)
-	chkerr(rderr)
-	for _, f := range files {
-		fname := f.Name()
-		if len(fname) > 4 {
-			if fname[len(fname)-4:] == bkpExt {
-				key := fname[0 : len(fname)-4]
-				fulp := fullpath(store, key)
-				msg, cerr := os.Create(fulp)
-				chkerr(cerr)
-				bkpp := path.Join(store, fname)
-				bkp, oerr := os.Open(bkpp)
-				chkerr(oerr)
-				n, cerr := io.Copy(msg, bkp)
-				chkerr(cerr)
-				chkcond(n > 0)
-				clmerr := msg.Close()
-				chkerr(clmerr)
-				clberr := bkp.Close()
-				chkerr(clberr)
-				remerr := os.Remove(bkpp)
-				chkerr(remerr)
-			}
-		}
-	}
-}
-
-func unbackup(store, key string) {
-	bkpp := bkppath(store, key)
-	remerr := os.Remove(bkpp)
-	chkerr(remerr)
-}

+ 0 - 119
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/memstore.go

@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2013 IBM Corp.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Seth Hoenig
- *    Allan Stockdill-Mander
- *    Mike Robertson
- */
-
-package mqtt
-
-import (
-	"git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets"
-	"sync"
-)
-
-// MemoryStore implements the store interface to provide a "persistence"
-// mechanism wholly stored in memory. This is only useful for
-// as long as the client instance exists.
-type MemoryStore struct {
-	sync.RWMutex
-	messages map[string]packets.ControlPacket
-	opened   bool
-}
-
-// NewMemoryStore returns a pointer to a new instance of
-// MemoryStore, the instance is not initialized and ready to
-// use until Open() has been called on it.
-func NewMemoryStore() *MemoryStore {
-	store := &MemoryStore{
-		messages: make(map[string]packets.ControlPacket),
-		opened:   false,
-	}
-	return store
-}
-
-// Open initializes a MemoryStore instance.
-func (store *MemoryStore) Open() {
-	store.Lock()
-	defer store.Unlock()
-	store.opened = true
-	DEBUG.Println(STR, "memorystore initialized")
-}
-
-// Put takes a key and a pointer to a Message and stores the
-// message.
-func (store *MemoryStore) Put(key string, message packets.ControlPacket) {
-	store.Lock()
-	defer store.Unlock()
-	chkcond(store.opened)
-	store.messages[key] = message
-}
-
-// Get takes a key and looks in the store for a matching Message
-// returning either the Message pointer or nil.
-func (store *MemoryStore) Get(key string) packets.ControlPacket {
-	store.RLock()
-	defer store.RUnlock()
-	chkcond(store.opened)
-	mid := mIDFromKey(key)
-	m := store.messages[key]
-	if m == nil {
-		CRITICAL.Println(STR, "memorystore get: message", mid, "not found")
-	} else {
-		DEBUG.Println(STR, "memorystore get: message", mid, "found")
-	}
-	return m
-}
-
-// All returns a slice of strings containing all the keys currently
-// in the MemoryStore.
-func (store *MemoryStore) All() []string {
-	store.RLock()
-	defer store.RUnlock()
-	chkcond(store.opened)
-	keys := []string{}
-	for k := range store.messages {
-		keys = append(keys, k)
-	}
-	return keys
-}
-
-// Del takes a key, searches the MemoryStore and if the key is found
-// deletes the Message pointer associated with it.
-func (store *MemoryStore) Del(key string) {
-	store.Lock()
-	defer store.Unlock()
-	mid := mIDFromKey(key)
-	m := store.messages[key]
-	if m == nil {
-		WARN.Println(STR, "memorystore del: message", mid, "not found")
-	} else {
-		store.messages[key] = nil
-		DEBUG.Println(STR, "memorystore del: message", mid, "was deleted")
-	}
-}
-
-// Close will disallow modifications to the state of the store.
-func (store *MemoryStore) Close() {
-	store.Lock()
-	defer store.Unlock()
-	chkcond(store.opened)
-	store.opened = false
-	DEBUG.Println(STR, "memorystore closed")
-}
-
-// Reset eliminates all persisted message data in the store.
-func (store *MemoryStore) Reset() {
-	store.Lock()
-	defer store.Unlock()
-	chkcond(store.opened)
-	store.messages = make(map[string]packets.ControlPacket)
-	WARN.Println(STR, "memorystore wiped")
-}

+ 0 - 104
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/message.go

@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2013 IBM Corp.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Seth Hoenig
- *    Allan Stockdill-Mander
- *    Mike Robertson
- */
-
-package mqtt
-
-import (
-	"git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets"
-)
-
-// Message defines the externals that a message implementation must support
-// these are received messages that are passed to the callbacks, not internal
-// messages
-type Message interface {
-	Duplicate() bool
-	Qos() byte
-	Retained() bool
-	Topic() string
-	MessageID() uint16
-	Payload() []byte
-}
-
-type message struct {
-	duplicate bool
-	qos       byte
-	retained  bool
-	topic     string
-	messageID uint16
-	payload   []byte
-}
-
-func (m *message) Duplicate() bool {
-	return m.duplicate
-}
-
-func (m *message) Qos() byte {
-	return m.qos
-}
-
-func (m *message) Retained() bool {
-	return m.retained
-}
-
-func (m *message) Topic() string {
-	return m.topic
-}
-
-func (m *message) MessageID() uint16 {
-	return m.messageID
-}
-
-func (m *message) Payload() []byte {
-	return m.payload
-}
-
-func messageFromPublish(p *packets.PublishPacket) Message {
-	return &message{
-		duplicate: p.Dup,
-		qos:       p.Qos,
-		retained:  p.Retain,
-		topic:     p.TopicName,
-		messageID: p.MessageID,
-		payload:   p.Payload,
-	}
-}
-
-func newConnectMsgFromOptions(options *ClientOptions) *packets.ConnectPacket {
-	m := packets.NewControlPacket(packets.Connect).(*packets.ConnectPacket)
-
-	m.CleanSession = options.CleanSession
-	m.WillFlag = options.WillEnabled
-	m.WillRetain = options.WillRetained
-	m.ClientIdentifier = options.ClientID
-
-	if options.WillEnabled {
-		m.WillQos = options.WillQos
-		m.WillTopic = options.WillTopic
-		m.WillMessage = options.WillPayload
-	}
-
-	if options.Username != "" {
-		m.UsernameFlag = true
-		m.Username = options.Username
-		//mustn't have password without user as well
-		if options.Password != "" {
-			m.PasswordFlag = true
-			m.Password = []byte(options.Password)
-		}
-	}
-
-	m.KeepaliveTimer = uint16(options.KeepAlive)
-
-	return m
-}

+ 0 - 61
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/messageids.go

@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2013 IBM Corp.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Seth Hoenig
- *    Allan Stockdill-Mander
- *    Mike Robertson
- */
-
-package mqtt
-
-import (
-	"sync"
-)
-
-// MId is 16 bit message id as specified by the MQTT spec.
-// In general, these values should not be depended upon by
-// the client application.
-type MId uint16
-
-type messageIds struct {
-	sync.RWMutex
-	index map[uint16]Token
-}
-
-const (
-	midMin uint16 = 1
-	midMax uint16 = 65535
-)
-
-func (mids *messageIds) freeID(id uint16) {
-	mids.Lock()
-	defer mids.Unlock()
-	delete(mids.index, id)
-}
-
-func (mids *messageIds) getID(t Token) uint16 {
-	mids.Lock()
-	defer mids.Unlock()
-	for i := midMin; i < midMax; i++ {
-		if _, ok := mids.index[i]; !ok {
-			mids.index[i] = t
-			return i
-		}
-	}
-	return 0
-}
-
-func (mids *messageIds) getToken(id uint16) Token {
-	mids.RLock()
-	defer mids.RUnlock()
-	if token, ok := mids.index[id]; ok {
-		return token
-	}
-	return nil
-}

+ 0 - 275
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/net.go

@@ -1,275 +0,0 @@
-/*
- * Copyright (c) 2013 IBM Corp.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Seth Hoenig
- *    Allan Stockdill-Mander
- *    Mike Robertson
- */
-
-package mqtt
-
-import (
-	"crypto/tls"
-	"errors"
-	"git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets"
-	"golang.org/x/net/websocket"
-	"net"
-	"net/url"
-	"reflect"
-	"time"
-)
-
-func openConnection(uri *url.URL, tlsc *tls.Config, timeout time.Duration) (net.Conn, error) {
-	switch uri.Scheme {
-	case "ws":
-		conn, err := websocket.Dial(uri.String(), "mqtt", "ws://localhost")
-		if err != nil {
-			return nil, err
-		}
-		conn.PayloadType = websocket.BinaryFrame
-		return conn, err
-	case "wss":
-		config, _ := websocket.NewConfig(uri.String(), "ws://localhost")
-		config.Protocol = []string{"mqtt"}
-		config.TlsConfig = tlsc
-		conn, err := websocket.DialConfig(config)
-		if err != nil {
-			return nil, err
-		}
-		conn.PayloadType = websocket.BinaryFrame
-		return conn, err
-	case "tcp":
-		conn, err := net.DialTimeout("tcp", uri.Host, timeout)
-		if err != nil {
-			return nil, err
-		}
-		return conn, nil
-	case "ssl":
-		fallthrough
-	case "tls":
-		fallthrough
-	case "tcps":
-		conn, err := tls.DialWithDialer(&net.Dialer{Timeout: timeout}, "tcp", uri.Host, tlsc)
-		if err != nil {
-			return nil, err
-		}
-		return conn, nil
-	}
-	return nil, errors.New("Unknown protocol")
-}
-
-// actually read incoming messages off the wire
-// send Message object into ibound channel
-func incoming(c *Client) {
-	defer c.workers.Done()
-	var err error
-	var cp packets.ControlPacket
-
-	DEBUG.Println(NET, "incoming started")
-
-	for {
-		if cp, err = packets.ReadPacket(c.conn); err != nil {
-			break
-		}
-		DEBUG.Println(NET, "Received Message")
-		c.ibound <- cp
-	}
-	// We received an error on read.
-	// If disconnect is in progress, swallow error and return
-	select {
-	case <-c.stop:
-		DEBUG.Println(NET, "incoming stopped")
-		return
-		// Not trying to disconnect, send the error to the errors channel
-	default:
-		ERROR.Println(NET, "incoming stopped with error")
-		c.errors <- err
-		return
-	}
-}
-
-// receive a Message object on obound, and then
-// actually send outgoing message to the wire
-func outgoing(c *Client) {
-	defer c.workers.Done()
-	DEBUG.Println(NET, "outgoing started")
-
-	for {
-		DEBUG.Println(NET, "outgoing waiting for an outbound message")
-		select {
-		case <-c.stop:
-			DEBUG.Println(NET, "outgoing stopped")
-			return
-		case pub := <-c.obound:
-			msg := pub.p.(*packets.PublishPacket)
-			if msg.Qos != 0 && msg.MessageID == 0 {
-				msg.MessageID = c.getID(pub.t)
-				pub.t.(*PublishToken).messageID = msg.MessageID
-			}
-			//persist_obound(c.persist, msg)
-
-			if c.options.WriteTimeout > 0 {
-				c.conn.SetWriteDeadline(time.Now().Add(c.options.WriteTimeout))
-			}
-
-			if err := msg.Write(c.conn); err != nil {
-				ERROR.Println(NET, "outgoing stopped with error")
-				c.errors <- err
-				return
-			}
-
-			if c.options.WriteTimeout > 0 {
-				// If we successfully wrote, we don't want the timeout to happen during an idle period
-				// so we reset it to infinite.
-				c.conn.SetWriteDeadline(time.Time{})
-			}
-
-			if msg.Qos == 0 {
-				pub.t.flowComplete()
-			}
-
-			c.lastContact.update()
-			DEBUG.Println(NET, "obound wrote msg, id:", msg.MessageID)
-		case msg := <-c.oboundP:
-			switch msg.p.(type) {
-			case *packets.SubscribePacket:
-				msg.p.(*packets.SubscribePacket).MessageID = c.getID(msg.t)
-			case *packets.UnsubscribePacket:
-				msg.p.(*packets.UnsubscribePacket).MessageID = c.getID(msg.t)
-			}
-			DEBUG.Println(NET, "obound priority msg to write, type", reflect.TypeOf(msg.p))
-			if err := msg.p.Write(c.conn); err != nil {
-				ERROR.Println(NET, "outgoing stopped with error")
-				c.errors <- err
-				return
-			}
-			c.lastContact.update()
-			switch msg.p.(type) {
-			case *packets.DisconnectPacket:
-				msg.t.(*DisconnectToken).flowComplete()
-				DEBUG.Println(NET, "outbound wrote disconnect, stopping")
-				return
-			}
-		}
-	}
-}
-
-// receive Message objects on ibound
-// store messages if necessary
-// send replies on obound
-// delete messages from store if necessary
-func alllogic(c *Client) {
-
-	DEBUG.Println(NET, "logic started")
-
-	for {
-		DEBUG.Println(NET, "logic waiting for msg on ibound")
-
-		select {
-		case msg := <-c.ibound:
-			DEBUG.Println(NET, "logic got msg on ibound")
-			//persist_ibound(c.persist, msg)
-			switch msg.(type) {
-			case *packets.PingrespPacket:
-				DEBUG.Println(NET, "received pingresp")
-				c.pingOutstanding = false
-			case *packets.SubackPacket:
-				sa := msg.(*packets.SubackPacket)
-				DEBUG.Println(NET, "received suback, id:", sa.MessageID)
-				token := c.getToken(sa.MessageID).(*SubscribeToken)
-				DEBUG.Println(NET, "granted qoss", sa.GrantedQoss)
-				for i, qos := range sa.GrantedQoss {
-					token.subResult[token.subs[i]] = qos
-				}
-				token.flowComplete()
-				go c.freeID(sa.MessageID)
-			case *packets.UnsubackPacket:
-				ua := msg.(*packets.UnsubackPacket)
-				DEBUG.Println(NET, "received unsuback, id:", ua.MessageID)
-				token := c.getToken(ua.MessageID).(*UnsubscribeToken)
-				token.flowComplete()
-				go c.freeID(ua.MessageID)
-			case *packets.PublishPacket:
-				pp := msg.(*packets.PublishPacket)
-				DEBUG.Println(NET, "received publish, msgId:", pp.MessageID)
-				DEBUG.Println(NET, "putting msg on onPubChan")
-				switch pp.Qos {
-				case 2:
-					c.incomingPubChan <- pp
-					DEBUG.Println(NET, "done putting msg on incomingPubChan")
-					pr := packets.NewControlPacket(packets.Pubrec).(*packets.PubrecPacket)
-					pr.MessageID = pp.MessageID
-					DEBUG.Println(NET, "putting pubrec msg on obound")
-					c.oboundP <- &PacketAndToken{p: pr, t: nil}
-					DEBUG.Println(NET, "done putting pubrec msg on obound")
-				case 1:
-					c.incomingPubChan <- pp
-					DEBUG.Println(NET, "done putting msg on incomingPubChan")
-					pa := packets.NewControlPacket(packets.Puback).(*packets.PubackPacket)
-					pa.MessageID = pp.MessageID
-					DEBUG.Println(NET, "putting puback msg on obound")
-					c.oboundP <- &PacketAndToken{p: pa, t: nil}
-					DEBUG.Println(NET, "done putting puback msg on obound")
-				case 0:
-					select {
-					case c.incomingPubChan <- pp:
-						DEBUG.Println(NET, "done putting msg on incomingPubChan")
-					case err, ok := <-c.errors:
-						DEBUG.Println(NET, "error while putting msg on pubChanZero")
-						// We are unblocked, but need to put the error back on so the outer
-						// select can handle it appropriately.
-						if ok {
-							go func(errVal error, errChan chan error) {
-								errChan <- errVal
-							}(err, c.errors)
-						}
-					}
-				}
-			case *packets.PubackPacket:
-				pa := msg.(*packets.PubackPacket)
-				DEBUG.Println(NET, "received puback, id:", pa.MessageID)
-				// c.receipts.get(msg.MsgId()) <- Receipt{}
-				// c.receipts.end(msg.MsgId())
-				c.getToken(pa.MessageID).flowComplete()
-				c.freeID(pa.MessageID)
-			case *packets.PubrecPacket:
-				prec := msg.(*packets.PubrecPacket)
-				DEBUG.Println(NET, "received pubrec, id:", prec.MessageID)
-				prel := packets.NewControlPacket(packets.Pubrel).(*packets.PubrelPacket)
-				prel.MessageID = prec.MessageID
-				select {
-				case c.oboundP <- &PacketAndToken{p: prel, t: nil}:
-				case <-time.After(time.Second):
-				}
-			case *packets.PubrelPacket:
-				pr := msg.(*packets.PubrelPacket)
-				DEBUG.Println(NET, "received pubrel, id:", pr.MessageID)
-				pc := packets.NewControlPacket(packets.Pubcomp).(*packets.PubcompPacket)
-				pc.MessageID = pr.MessageID
-				select {
-				case c.oboundP <- &PacketAndToken{p: pc, t: nil}:
-				case <-time.After(time.Second):
-				}
-			case *packets.PubcompPacket:
-				pc := msg.(*packets.PubcompPacket)
-				DEBUG.Println(NET, "received pubcomp, id:", pc.MessageID)
-				c.getToken(pc.MessageID).flowComplete()
-				c.freeID(pc.MessageID)
-			}
-		case <-c.stop:
-			WARN.Println(NET, "logic stopped")
-			return
-		case err := <-c.errors:
-			ERROR.Println(NET, "logic got error")
-			c.internalConnLost(err)
-			return
-		}
-		c.lastContact.update()
-	}
-}

+ 0 - 108
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/notice.html

@@ -1,108 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1" ?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
-<title>Eclipse Foundation Software User Agreement</title>
-</head>
-
-<body lang="EN-US">
-<h2>Eclipse Foundation Software User Agreement</h2>
-<p>February 1, 2011</p>
-
-<h3>Usage Of Content</h3>
-
-<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
-   (COLLECTIVELY &quot;CONTENT&quot;).  USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
-   CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW.  BY USING THE CONTENT, YOU AGREE THAT YOUR USE
-   OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
-   NOTICES INDICATED OR REFERENCED BELOW.  IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
-   CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p>
-
-<h3>Applicable Licenses</h3>
-
-<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0
-   (&quot;EPL&quot;).  A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
-   For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
-
-<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code
-   repository (&quot;Repository&quot;) in software modules (&quot;Modules&quot;) and made available as downloadable archives (&quot;Downloads&quot;).</p>
-
-<ul>
-       <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content.  Typical modules may include plug-ins (&quot;Plug-ins&quot;), plug-in fragments (&quot;Fragments&quot;), and features (&quot;Features&quot;).</li>
-       <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java&trade; ARchive) in a directory named &quot;plugins&quot;.</li>
-       <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.  Each Feature may be packaged as a sub-directory in a directory named &quot;features&quot;.  Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of the Plug-ins
-      and/or Fragments associated with that Feature.</li>
-       <li>Features may also include other Features (&quot;Included Features&quot;). Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of Included Features.</li>
-</ul>
-
-<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named &quot;about.html&quot; (&quot;Abouts&quot;). The terms and conditions governing Features and
-Included Features should be contained in files named &quot;license.html&quot; (&quot;Feature Licenses&quot;).  Abouts and Feature Licenses may be located in any directory of a Download or Module
-including, but not limited to the following locations:</p>
-
-<ul>
-       <li>The top-level (root) directory</li>
-       <li>Plug-in and Fragment directories</li>
-       <li>Inside Plug-ins and Fragments packaged as JARs</li>
-       <li>Sub-directories of the directory named &quot;src&quot; of certain Plug-ins</li>
-       <li>Feature directories</li>
-</ul>
-
-<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license (&quot;Feature Update License&quot;) during the
-installation process.  If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
-inform you where you can locate them.  Feature Update Licenses may be found in the &quot;license&quot; property of files named &quot;feature.properties&quot; found within a Feature.
-Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
-that directory.</p>
-
-<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.  SOME OF THESE
-OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p>
-
-<ul>
-       <li>Eclipse Distribution License Version 1.0 (available at <a href="http://www.eclipse.org/licenses/edl-v10.html">http://www.eclipse.org/licenses/edl-v1.0.html</a>)</li>
-       <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li>
-       <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li>
-       <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
-       <li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li>
-       <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li>
-</ul>
-
-<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT.  If no About, Feature License, or Feature Update License is provided, please
-contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p>
-
-
-<h3>Use of Provisioning Technology</h3>
-
-<p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse
-   Update Manager (&quot;Provisioning Technology&quot;) for the purpose of allowing users to install software, documentation, information and/or
-   other materials (collectively &quot;Installable Software&quot;). This capability is provided with the intent of allowing such users to
-   install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a
-       href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a>
-   (&quot;Specification&quot;).</p>
-
-<p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the
-   applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology
-   in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the
-   Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p>
-
-<ol>
-       <li>A series of actions may occur (&quot;Provisioning Process&quot;) in which a user may execute the Provisioning Technology
-       on a machine (&quot;Target Machine&quot;) with the intent of installing, extending or updating the functionality of an Eclipse-based
-       product.</li>
-       <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be
-       accessed and copied to the Target Machine.</li>
-       <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable
-       Software (&quot;Installable Software Agreement&quot;) and such Installable Software Agreement shall be accessed from the Target
-       Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern
-       the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such
-       indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li>
-</ol>
-
-<h3>Cryptography</h3>
-
-<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
-   another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
-   possession, or use, and re-export of encryption software, to see if this is permitted.</p>
-
-<p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p>
-</body>
-</html>

+ 0 - 27
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/oops.go

@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2013 IBM Corp.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Seth Hoenig
- *    Allan Stockdill-Mander
- *    Mike Robertson
- */
-
-package mqtt
-
-func chkerr(e error) {
-	if e != nil {
-		panic(e)
-	}
-}
-
-func chkcond(b bool) {
-	if !b {
-		panic("oops")
-	}
-}

+ 0 - 270
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/options.go

@@ -1,270 +0,0 @@
-/*
- * Copyright (c) 2013 IBM Corp.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Seth Hoenig
- *    Allan Stockdill-Mander
- *    Mike Robertson
- */
-
-package mqtt
-
-import (
-	"crypto/tls"
-	"net/url"
-	"time"
-)
-
-// MessageHandler is a callback type which can be set to be
-// executed upon the arrival of messages published to topics
-// to which the client is subscribed.
-type MessageHandler func(*Client, Message)
-
-// ConnectionLostHandler is a callback type which can be set to be
-// executed upon an unintended disconnection from the MQTT broker.
-// Disconnects caused by calling Disconnect or ForceDisconnect will
-// not cause an OnConnectionLost callback to execute.
-type ConnectionLostHandler func(*Client, error)
-
-// OnConnectHandler is a callback that is called when the client
-// state changes from unconnected/disconnected to connected. Both
-// at initial connection and on reconnection
-type OnConnectHandler func(*Client)
-
-// ClientOptions contains configurable options for an Client.
-type ClientOptions struct {
-	Servers                 []*url.URL
-	ClientID                string
-	Username                string
-	Password                string
-	CleanSession            bool
-	Order                   bool
-	WillEnabled             bool
-	WillTopic               string
-	WillPayload             []byte
-	WillQos                 byte
-	WillRetained            bool
-	ProtocolVersion         uint
-	protocolVersionExplicit bool
-	TLSConfig               tls.Config
-	KeepAlive               time.Duration
-	ConnectTimeout          time.Duration
-	MaxReconnectInterval    time.Duration
-	AutoReconnect           bool
-	Store                   Store
-	DefaultPublishHander    MessageHandler
-	OnConnect               OnConnectHandler
-	OnConnectionLost        ConnectionLostHandler
-	WriteTimeout            time.Duration
-}
-
-// NewClientOptions will create a new ClientClientOptions type with some
-// default values.
-//   Port: 1883
-//   CleanSession: True
-//   Order: True
-//   KeepAlive: 30 (seconds)
-//   ConnectTimeout: 30 (seconds)
-//   MaxReconnectInterval 10 (minutes)
-//   AutoReconnect: True
-func NewClientOptions() *ClientOptions {
-	o := &ClientOptions{
-		Servers:                 nil,
-		ClientID:                "",
-		Username:                "",
-		Password:                "",
-		CleanSession:            true,
-		Order:                   true,
-		WillEnabled:             false,
-		WillTopic:               "",
-		WillPayload:             nil,
-		WillQos:                 0,
-		WillRetained:            false,
-		ProtocolVersion:         0,
-		protocolVersionExplicit: false,
-		TLSConfig:               tls.Config{},
-		KeepAlive:               30 * time.Second,
-		ConnectTimeout:          30 * time.Second,
-		MaxReconnectInterval:    10 * time.Minute,
-		AutoReconnect:           true,
-		Store:                   nil,
-		OnConnect:               nil,
-		OnConnectionLost:        DefaultConnectionLostHandler,
-		WriteTimeout:            0, // 0 represents timeout disabled
-	}
-	return o
-}
-
-// AddBroker adds a broker URI to the list of brokers to be used. The format should be
-// scheme://host:port
-// Where "scheme" is one of "tcp", "ssl", or "ws", "host" is the ip-address (or hostname)
-// and "port" is the port on which the broker is accepting connections.
-func (o *ClientOptions) AddBroker(server string) *ClientOptions {
-	brokerURI, _ := url.Parse(server)
-	o.Servers = append(o.Servers, brokerURI)
-	return o
-}
-
-// SetClientID will set the client id to be used by this client when
-// connecting to the MQTT broker. According to the MQTT v3.1 specification,
-// a client id mus be no longer than 23 characters.
-func (o *ClientOptions) SetClientID(id string) *ClientOptions {
-	o.ClientID = id
-	return o
-}
-
-// SetUsername will set the username to be used by this client when connecting
-// to the MQTT broker. Note: without the use of SSL/TLS, this information will
-// be sent in plaintext accross the wire.
-func (o *ClientOptions) SetUsername(u string) *ClientOptions {
-	o.Username = u
-	return o
-}
-
-// SetPassword will set the password to be used by this client when connecting
-// to the MQTT broker. Note: without the use of SSL/TLS, this information will
-// be sent in plaintext accross the wire.
-func (o *ClientOptions) SetPassword(p string) *ClientOptions {
-	o.Password = p
-	return o
-}
-
-// SetCleanSession will set the "clean session" flag in the connect message
-// when this client connects to an MQTT broker. By setting this flag, you are
-// indicating that no messages saved by the broker for this client should be
-// delivered. Any messages that were going to be sent by this client before
-// diconnecting previously but didn't will not be sent upon connecting to the
-// broker.
-func (o *ClientOptions) SetCleanSession(clean bool) *ClientOptions {
-	o.CleanSession = clean
-	return o
-}
-
-// SetOrderMatters will set the message routing to guarantee order within
-// each QoS level. By default, this value is true. If set to false,
-// this flag indicates that messages can be delivered asynchronously
-// from the client to the application and possibly arrive out of order.
-func (o *ClientOptions) SetOrderMatters(order bool) *ClientOptions {
-	o.Order = order
-	return o
-}
-
-// SetTLSConfig will set an SSL/TLS configuration to be used when connecting
-// to an MQTT broker. Please read the official Go documentation for more
-// information.
-func (o *ClientOptions) SetTLSConfig(t *tls.Config) *ClientOptions {
-	o.TLSConfig = *t
-	return o
-}
-
-// SetStore will set the implementation of the Store interface
-// used to provide message persistence in cases where QoS levels
-// QoS_ONE or QoS_TWO are used. If no store is provided, then the
-// client will use MemoryStore by default.
-func (o *ClientOptions) SetStore(s Store) *ClientOptions {
-	o.Store = s
-	return o
-}
-
-// SetKeepAlive will set the amount of time (in seconds) that the client
-// should wait before sending a PING request to the broker. This will
-// allow the client to know that a connection has not been lost with the
-// server.
-func (o *ClientOptions) SetKeepAlive(k time.Duration) *ClientOptions {
-	o.KeepAlive = k
-	return o
-}
-
-// SetProtocolVersion sets the MQTT version to be used to connect to the
-// broker. Legitimate values are currently 3 - MQTT 3.1 or 4 - MQTT 3.1.1
-func (o *ClientOptions) SetProtocolVersion(pv uint) *ClientOptions {
-	if pv >= 3 && pv <= 4 {
-		o.ProtocolVersion = pv
-		o.protocolVersionExplicit = true
-	}
-	return o
-}
-
-// UnsetWill will cause any set will message to be disregarded.
-func (o *ClientOptions) UnsetWill() *ClientOptions {
-	o.WillEnabled = false
-	return o
-}
-
-// SetWill accepts a string will message to be set. When the client connects,
-// it will give this will message to the broker, which will then publish the
-// provided payload (the will) to any clients that are subscribed to the provided
-// topic.
-func (o *ClientOptions) SetWill(topic string, payload string, qos byte, retained bool) *ClientOptions {
-	o.SetBinaryWill(topic, []byte(payload), qos, retained)
-	return o
-}
-
-// SetBinaryWill accepts a []byte will message to be set. When the client connects,
-// it will give this will message to the broker, which will then publish the
-// provided payload (the will) to any clients that are subscribed to the provided
-// topic.
-func (o *ClientOptions) SetBinaryWill(topic string, payload []byte, qos byte, retained bool) *ClientOptions {
-	o.WillEnabled = true
-	o.WillTopic = topic
-	o.WillPayload = payload
-	o.WillQos = qos
-	o.WillRetained = retained
-	return o
-}
-
-// SetDefaultPublishHandler sets the MessageHandler that will be called when a message
-// is received that does not match any known subscriptions.
-func (o *ClientOptions) SetDefaultPublishHandler(defaultHandler MessageHandler) *ClientOptions {
-	o.DefaultPublishHander = defaultHandler
-	return o
-}
-
-// SetOnConnectHandler sets the function to be called when the client is connected. Both
-// at initial connection time and upon automatic reconnect.
-func (o *ClientOptions) SetOnConnectHandler(onConn OnConnectHandler) *ClientOptions {
-	o.OnConnect = onConn
-	return o
-}
-
-// SetConnectionLostHandler will set the OnConnectionLost callback to be executed
-// in the case where the client unexpectedly loses connection with the MQTT broker.
-func (o *ClientOptions) SetConnectionLostHandler(onLost ConnectionLostHandler) *ClientOptions {
-	o.OnConnectionLost = onLost
-	return o
-}
-
-// SetWriteTimeout puts a limit on how long a mqtt publish should block until it unblocks with a
-// timeout error. A duration of 0 never times out. Default 30 seconds
-func (o *ClientOptions) SetWriteTimeout(t time.Duration) *ClientOptions {
-	o.WriteTimeout = t
-	return o
-}
-
-// SetConnectTimeout limits how long the client will wait when trying to open a connection
-// to an MQTT server before timeing out and erroring the attempt. A duration of 0 never times out.
-// Default 30 seconds. Currently only operational on TCP/TLS connections.
-func (o *ClientOptions) SetConnectTimeout(t time.Duration) *ClientOptions {
-	o.ConnectTimeout = t
-	return o
-}
-
-// SetMaxReconnectInterval sets the maximum time that will be waited between reconnection attempts
-// when connection is lost
-func (o *ClientOptions) SetMaxReconnectInterval(t time.Duration) *ClientOptions {
-	o.MaxReconnectInterval = t
-	return o
-}
-
-// SetAutoReconnect sets whether the automatic reconnection logic should be used
-// when the connection is lost, even if disabled the ConnectionLostHandler is still
-// called
-func (o *ClientOptions) SetAutoReconnect(a bool) *ClientOptions {
-	o.AutoReconnect = a
-	return o
-}

+ 0 - 57
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/connack.go

@@ -1,57 +0,0 @@
-package packets
-
-import (
-	"bytes"
-	"fmt"
-	"github.com/pborman/uuid"
-	"io"
-)
-
-//ConnackPacket is an internal representation of the fields of the
-//Connack MQTT packet
-type ConnackPacket struct {
-	FixedHeader
-	TopicNameCompression byte
-	ReturnCode           byte
-	uuid                 uuid.UUID
-}
-
-func (ca *ConnackPacket) String() string {
-	str := fmt.Sprintf("%s\n", ca.FixedHeader)
-	str += fmt.Sprintf("returncode: %d", ca.ReturnCode)
-	return str
-}
-
-func (ca *ConnackPacket) Write(w io.Writer) error {
-	var body bytes.Buffer
-	var err error
-
-	body.WriteByte(ca.TopicNameCompression)
-	body.WriteByte(ca.ReturnCode)
-	ca.FixedHeader.RemainingLength = 2
-	packet := ca.FixedHeader.pack()
-	packet.Write(body.Bytes())
-	_, err = packet.WriteTo(w)
-
-	return err
-}
-
-//Unpack decodes the details of a ControlPacket after the fixed
-//header has been read
-func (ca *ConnackPacket) Unpack(b io.Reader) {
-	ca.TopicNameCompression = decodeByte(b)
-	ca.ReturnCode = decodeByte(b)
-}
-
-//Details returns a Details struct containing the Qos and
-//MessageID of this ControlPacket
-func (ca *ConnackPacket) Details() Details {
-	return Details{Qos: 0, MessageID: 0}
-}
-
-//UUID returns the unique ID assigned to the ControlPacket when
-//it was originally received. Note: this is not related to the
-//MessageID field for MQTT packets
-func (ca *ConnackPacket) UUID() uuid.UUID {
-	return ca.uuid
-}

+ 0 - 128
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/connect.go

@@ -1,128 +0,0 @@
-package packets
-
-import (
-	"bytes"
-	"fmt"
-	"github.com/pborman/uuid"
-	"io"
-)
-
-//ConnectPacket is an internal representation of the fields of the
-//Connect MQTT packet
-type ConnectPacket struct {
-	FixedHeader
-	ProtocolName    string
-	ProtocolVersion byte
-	CleanSession    bool
-	WillFlag        bool
-	WillQos         byte
-	WillRetain      bool
-	UsernameFlag    bool
-	PasswordFlag    bool
-	ReservedBit     byte
-	KeepaliveTimer  uint16
-
-	ClientIdentifier string
-	WillTopic        string
-	WillMessage      []byte
-	Username         string
-	Password         []byte
-	uuid             uuid.UUID
-}
-
-func (c *ConnectPacket) String() string {
-	str := fmt.Sprintf("%s\n", c.FixedHeader)
-	str += fmt.Sprintf("protocolversion: %d protocolname: %s cleansession: %t willflag: %t WillQos: %d WillRetain: %t Usernameflag: %t Passwordflag: %t keepalivetimer: %d\nclientId: %s\nwilltopic: %s\nwillmessage: %s\nUsername: %s\nPassword: %s\n", c.ProtocolVersion, c.ProtocolName, c.CleanSession, c.WillFlag, c.WillQos, c.WillRetain, c.UsernameFlag, c.PasswordFlag, c.KeepaliveTimer, c.ClientIdentifier, c.WillTopic, c.WillMessage, c.Username, c.Password)
-	return str
-}
-
-func (c *ConnectPacket) Write(w io.Writer) error {
-	var body bytes.Buffer
-	var err error
-
-	body.Write(encodeString(c.ProtocolName))
-	body.WriteByte(c.ProtocolVersion)
-	body.WriteByte(boolToByte(c.CleanSession)<<1 | boolToByte(c.WillFlag)<<2 | c.WillQos<<3 | boolToByte(c.WillRetain)<<5 | boolToByte(c.PasswordFlag)<<6 | boolToByte(c.UsernameFlag)<<7)
-	body.Write(encodeUint16(c.KeepaliveTimer))
-	body.Write(encodeString(c.ClientIdentifier))
-	if c.WillFlag {
-		body.Write(encodeString(c.WillTopic))
-		body.Write(encodeBytes(c.WillMessage))
-	}
-	if c.UsernameFlag {
-		body.Write(encodeString(c.Username))
-	}
-	if c.PasswordFlag {
-		body.Write(encodeBytes(c.Password))
-	}
-	c.FixedHeader.RemainingLength = body.Len()
-	packet := c.FixedHeader.pack()
-	packet.Write(body.Bytes())
-	_, err = packet.WriteTo(w)
-
-	return err
-}
-
-//Unpack decodes the details of a ControlPacket after the fixed
-//header has been read
-func (c *ConnectPacket) Unpack(b io.Reader) {
-	c.ProtocolName = decodeString(b)
-	c.ProtocolVersion = decodeByte(b)
-	options := decodeByte(b)
-	c.ReservedBit = 1 & options
-	c.CleanSession = 1&(options>>1) > 0
-	c.WillFlag = 1&(options>>2) > 0
-	c.WillQos = 3 & (options >> 3)
-	c.WillRetain = 1&(options>>5) > 0
-	c.PasswordFlag = 1&(options>>6) > 0
-	c.UsernameFlag = 1&(options>>7) > 0
-	c.KeepaliveTimer = decodeUint16(b)
-	c.ClientIdentifier = decodeString(b)
-	if c.WillFlag {
-		c.WillTopic = decodeString(b)
-		c.WillMessage = decodeBytes(b)
-	}
-	if c.UsernameFlag {
-		c.Username = decodeString(b)
-	}
-	if c.PasswordFlag {
-		c.Password = decodeBytes(b)
-	}
-}
-
-//Validate performs validation of the fields of a Connect packet
-func (c *ConnectPacket) Validate() byte {
-	if c.PasswordFlag && !c.UsernameFlag {
-		return ErrRefusedBadUsernameOrPassword
-	}
-	if c.ReservedBit != 0 {
-		//Bad reserved bit
-		return ErrProtocolViolation
-	}
-	if (c.ProtocolName == "MQIsdp" && c.ProtocolVersion != 3) || (c.ProtocolName == "MQTT" && c.ProtocolVersion != 4) {
-		//Mismatched or unsupported protocol version
-		return ErrRefusedBadProtocolVersion
-	}
-	if c.ProtocolName != "MQIsdp" && c.ProtocolName != "MQTT" {
-		//Bad protocol name
-		return ErrProtocolViolation
-	}
-	if len(c.ClientIdentifier) > 65535 || len(c.Username) > 65535 || len(c.Password) > 65535 {
-		//Bad size field
-		return ErrProtocolViolation
-	}
-	return Accepted
-}
-
-//Details returns a Details struct containing the Qos and
-//MessageID of this ControlPacket
-func (c *ConnectPacket) Details() Details {
-	return Details{Qos: 0, MessageID: 0}
-}
-
-//UUID returns the unique ID assigned to the ControlPacket when
-//it was originally received. Note: this is not related to the
-//MessageID field for MQTT packets
-func (c *ConnectPacket) UUID() uuid.UUID {
-	return c.uuid
-}

+ 0 - 44
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/disconnect.go

@@ -1,44 +0,0 @@
-package packets
-
-import (
-	"fmt"
-	"github.com/pborman/uuid"
-	"io"
-)
-
-//DisconnectPacket is an internal representation of the fields of the
-//Disconnect MQTT packet
-type DisconnectPacket struct {
-	FixedHeader
-	uuid uuid.UUID
-}
-
-func (d *DisconnectPacket) String() string {
-	str := fmt.Sprintf("%s\n", d.FixedHeader)
-	return str
-}
-
-func (d *DisconnectPacket) Write(w io.Writer) error {
-	packet := d.FixedHeader.pack()
-	_, err := packet.WriteTo(w)
-
-	return err
-}
-
-//Unpack decodes the details of a ControlPacket after the fixed
-//header has been read
-func (d *DisconnectPacket) Unpack(b io.Reader) {
-}
-
-//Details returns a Details struct containing the Qos and
-//MessageID of this ControlPacket
-func (d *DisconnectPacket) Details() Details {
-	return Details{Qos: 0, MessageID: 0}
-}
-
-//UUID returns the unique ID assigned to the ControlPacket when
-//it was originally received. Note: this is not related to the
-//MessageID field for MQTT packets
-func (d *DisconnectPacket) UUID() uuid.UUID {
-	return d.uuid
-}

+ 0 - 324
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/packets.go

@@ -1,324 +0,0 @@
-package packets
-
-import (
-	"bytes"
-	"encoding/binary"
-	"errors"
-	"fmt"
-	"github.com/pborman/uuid"
-	"io"
-)
-
-//ControlPacket defines the interface for structs intended to hold
-//decoded MQTT packets, either from being read or before being
-//written
-type ControlPacket interface {
-	Write(io.Writer) error
-	Unpack(io.Reader)
-	String() string
-	Details() Details
-	UUID() uuid.UUID
-}
-
-//PacketNames maps the constants for each of the MQTT packet types
-//to a string representation of their name.
-var PacketNames = map[uint8]string{
-	1:  "CONNECT",
-	2:  "CONNACK",
-	3:  "PUBLISH",
-	4:  "PUBACK",
-	5:  "PUBREC",
-	6:  "PUBREL",
-	7:  "PUBCOMP",
-	8:  "SUBSCRIBE",
-	9:  "SUBACK",
-	10: "UNSUBSCRIBE",
-	11: "UNSUBACK",
-	12: "PINGREQ",
-	13: "PINGRESP",
-	14: "DISCONNECT",
-}
-
-//Below are the constants assigned to each of the MQTT packet types
-const (
-	Connect     = 1
-	Connack     = 2
-	Publish     = 3
-	Puback      = 4
-	Pubrec      = 5
-	Pubrel      = 6
-	Pubcomp     = 7
-	Subscribe   = 8
-	Suback      = 9
-	Unsubscribe = 10
-	Unsuback    = 11
-	Pingreq     = 12
-	Pingresp    = 13
-	Disconnect  = 14
-)
-
-//Below are the const definitions for error codes returned by
-//Connect()
-const (
-	Accepted                        = 0x00
-	ErrRefusedBadProtocolVersion    = 0x01
-	ErrRefusedIDRejected            = 0x02
-	ErrRefusedServerUnavailable     = 0x03
-	ErrRefusedBadUsernameOrPassword = 0x04
-	ErrRefusedNotAuthorised         = 0x05
-	ErrNetworkError                 = 0xFE
-	ErrProtocolViolation            = 0xFF
-)
-
-//ConnackReturnCodes is a map of the error codes constants for Connect()
-//to a string representation of the error
-var ConnackReturnCodes = map[uint8]string{
-	0:   "Connection Accepted",
-	1:   "Connection Refused: Bad Protocol Version",
-	2:   "Connection Refused: Client Identifier Rejected",
-	3:   "Connection Refused: Server Unavailable",
-	4:   "Connection Refused: Username or Password in unknown format",
-	5:   "Connection Refused: Not Authorised",
-	254: "Connection Error",
-	255: "Connection Refused: Protocol Violation",
-}
-
-//ConnErrors is a map of the errors codes constants for Connect()
-//to a Go error
-var ConnErrors = map[byte]error{
-	Accepted:                        nil,
-	ErrRefusedBadProtocolVersion:    errors.New("Unnacceptable protocol version"),
-	ErrRefusedIDRejected:            errors.New("Identifier rejected"),
-	ErrRefusedServerUnavailable:     errors.New("Server Unavailable"),
-	ErrRefusedBadUsernameOrPassword: errors.New("Bad user name or password"),
-	ErrRefusedNotAuthorised:         errors.New("Not Authorized"),
-	ErrNetworkError:                 errors.New("Network Error"),
-	ErrProtocolViolation:            errors.New("Protocol Violation"),
-}
-
-//ReadPacket takes an instance of an io.Reader (such as net.Conn) and attempts
-//to read an MQTT packet from the stream. It returns a ControlPacket
-//representing the decoded MQTT packet and an error. One of these returns will
-//always be nil, a nil ControlPacket indicating an error occurred.
-func ReadPacket(r io.Reader) (cp ControlPacket, err error) {
-	var fh FixedHeader
-	b := make([]byte, 1)
-
-	_, err = io.ReadFull(r, b)
-	if err != nil {
-		return nil, err
-	}
-	fh.unpack(b[0], r)
-	cp = NewControlPacketWithHeader(fh)
-	if cp == nil {
-		return nil, errors.New("Bad data from client")
-	}
-	packetBytes := make([]byte, fh.RemainingLength)
-	_, err = io.ReadFull(r, packetBytes)
-	if err != nil {
-		return nil, err
-	}
-	cp.Unpack(bytes.NewBuffer(packetBytes))
-	return cp, nil
-}
-
-//NewControlPacket is used to create a new ControlPacket of the type specified
-//by packetType, this is usually done by reference to the packet type constants
-//defined in packets.go. The newly created ControlPacket is empty and a pointer
-//is returned.
-func NewControlPacket(packetType byte) (cp ControlPacket) {
-	switch packetType {
-	case Connect:
-		cp = &ConnectPacket{FixedHeader: FixedHeader{MessageType: Connect}, uuid: uuid.NewUUID()}
-	case Connack:
-		cp = &ConnackPacket{FixedHeader: FixedHeader{MessageType: Connack}, uuid: uuid.NewUUID()}
-	case Disconnect:
-		cp = &DisconnectPacket{FixedHeader: FixedHeader{MessageType: Disconnect}, uuid: uuid.NewUUID()}
-	case Publish:
-		cp = &PublishPacket{FixedHeader: FixedHeader{MessageType: Publish}, uuid: uuid.NewUUID()}
-	case Puback:
-		cp = &PubackPacket{FixedHeader: FixedHeader{MessageType: Puback}, uuid: uuid.NewUUID()}
-	case Pubrec:
-		cp = &PubrecPacket{FixedHeader: FixedHeader{MessageType: Pubrec}, uuid: uuid.NewUUID()}
-	case Pubrel:
-		cp = &PubrelPacket{FixedHeader: FixedHeader{MessageType: Pubrel, Qos: 1}, uuid: uuid.NewUUID()}
-	case Pubcomp:
-		cp = &PubcompPacket{FixedHeader: FixedHeader{MessageType: Pubcomp}, uuid: uuid.NewUUID()}
-	case Subscribe:
-		cp = &SubscribePacket{FixedHeader: FixedHeader{MessageType: Subscribe, Qos: 1}, uuid: uuid.NewUUID()}
-	case Suback:
-		cp = &SubackPacket{FixedHeader: FixedHeader{MessageType: Suback}, uuid: uuid.NewUUID()}
-	case Unsubscribe:
-		cp = &UnsubscribePacket{FixedHeader: FixedHeader{MessageType: Unsubscribe, Qos: 1}, uuid: uuid.NewUUID()}
-	case Unsuback:
-		cp = &UnsubackPacket{FixedHeader: FixedHeader{MessageType: Unsuback}, uuid: uuid.NewUUID()}
-	case Pingreq:
-		cp = &PingreqPacket{FixedHeader: FixedHeader{MessageType: Pingreq}, uuid: uuid.NewUUID()}
-	case Pingresp:
-		cp = &PingrespPacket{FixedHeader: FixedHeader{MessageType: Pingresp}, uuid: uuid.NewUUID()}
-	default:
-		return nil
-	}
-	return cp
-}
-
-//NewControlPacketWithHeader is used to create a new ControlPacket of the type
-//specified within the FixedHeader that is passed to the function.
-//The newly created ControlPacket is empty and a pointer is returned.
-func NewControlPacketWithHeader(fh FixedHeader) (cp ControlPacket) {
-	switch fh.MessageType {
-	case Connect:
-		cp = &ConnectPacket{FixedHeader: fh, uuid: uuid.NewUUID()}
-	case Connack:
-		cp = &ConnackPacket{FixedHeader: fh, uuid: uuid.NewUUID()}
-	case Disconnect:
-		cp = &DisconnectPacket{FixedHeader: fh, uuid: uuid.NewUUID()}
-	case Publish:
-		cp = &PublishPacket{FixedHeader: fh, uuid: uuid.NewUUID()}
-	case Puback:
-		cp = &PubackPacket{FixedHeader: fh, uuid: uuid.NewUUID()}
-	case Pubrec:
-		cp = &PubrecPacket{FixedHeader: fh, uuid: uuid.NewUUID()}
-	case Pubrel:
-		cp = &PubrelPacket{FixedHeader: fh, uuid: uuid.NewUUID()}
-	case Pubcomp:
-		cp = &PubcompPacket{FixedHeader: fh, uuid: uuid.NewUUID()}
-	case Subscribe:
-		cp = &SubscribePacket{FixedHeader: fh, uuid: uuid.NewUUID()}
-	case Suback:
-		cp = &SubackPacket{FixedHeader: fh, uuid: uuid.NewUUID()}
-	case Unsubscribe:
-		cp = &UnsubscribePacket{FixedHeader: fh, uuid: uuid.NewUUID()}
-	case Unsuback:
-		cp = &UnsubackPacket{FixedHeader: fh, uuid: uuid.NewUUID()}
-	case Pingreq:
-		cp = &PingreqPacket{FixedHeader: fh, uuid: uuid.NewUUID()}
-	case Pingresp:
-		cp = &PingrespPacket{FixedHeader: fh, uuid: uuid.NewUUID()}
-	default:
-		return nil
-	}
-	return cp
-}
-
-//Details struct returned by the Details() function called on
-//ControlPackets to present details of the Qos and MessageID
-//of the ControlPacket
-type Details struct {
-	Qos       byte
-	MessageID uint16
-}
-
-//FixedHeader is a struct to hold the decoded information from
-//the fixed header of an MQTT ControlPacket
-type FixedHeader struct {
-	MessageType     byte
-	Dup             bool
-	Qos             byte
-	Retain          bool
-	RemainingLength int
-}
-
-func (fh FixedHeader) String() string {
-	return fmt.Sprintf("%s: dup: %t qos: %d retain: %t rLength: %d", PacketNames[fh.MessageType], fh.Dup, fh.Qos, fh.Retain, fh.RemainingLength)
-}
-
-func boolToByte(b bool) byte {
-	switch b {
-	case true:
-		return 1
-	default:
-		return 0
-	}
-}
-
-func (fh *FixedHeader) pack() bytes.Buffer {
-	var header bytes.Buffer
-	header.WriteByte(fh.MessageType<<4 | boolToByte(fh.Dup)<<3 | fh.Qos<<1 | boolToByte(fh.Retain))
-	header.Write(encodeLength(fh.RemainingLength))
-	return header
-}
-
-func (fh *FixedHeader) unpack(typeAndFlags byte, r io.Reader) {
-	fh.MessageType = typeAndFlags >> 4
-	fh.Dup = (typeAndFlags>>3)&0x01 > 0
-	fh.Qos = (typeAndFlags >> 1) & 0x03
-	fh.Retain = typeAndFlags&0x01 > 0
-	fh.RemainingLength = decodeLength(r)
-}
-
-func decodeByte(b io.Reader) byte {
-	num := make([]byte, 1)
-	b.Read(num)
-	return num[0]
-}
-
-func decodeUint16(b io.Reader) uint16 {
-	num := make([]byte, 2)
-	b.Read(num)
-	return binary.BigEndian.Uint16(num)
-}
-
-func encodeUint16(num uint16) []byte {
-	bytes := make([]byte, 2)
-	binary.BigEndian.PutUint16(bytes, num)
-	return bytes
-}
-
-func encodeString(field string) []byte {
-	fieldLength := make([]byte, 2)
-	binary.BigEndian.PutUint16(fieldLength, uint16(len(field)))
-	return append(fieldLength, []byte(field)...)
-}
-
-func decodeString(b io.Reader) string {
-	fieldLength := decodeUint16(b)
-	field := make([]byte, fieldLength)
-	b.Read(field)
-	return string(field)
-}
-
-func decodeBytes(b io.Reader) []byte {
-	fieldLength := decodeUint16(b)
-	field := make([]byte, fieldLength)
-	b.Read(field)
-	return field
-}
-
-func encodeBytes(field []byte) []byte {
-	fieldLength := make([]byte, 2)
-	binary.BigEndian.PutUint16(fieldLength, uint16(len(field)))
-	return append(fieldLength, field...)
-}
-
-func encodeLength(length int) []byte {
-	var encLength []byte
-	for {
-		digit := byte(length % 128)
-		length /= 128
-		if length > 0 {
-			digit |= 0x80
-		}
-		encLength = append(encLength, digit)
-		if length == 0 {
-			break
-		}
-	}
-	return encLength
-}
-
-func decodeLength(r io.Reader) int {
-	var rLength uint32
-	var multiplier uint32
-	b := make([]byte, 1)
-	for {
-		io.ReadFull(r, b)
-		digit := b[0]
-		rLength |= uint32(digit&127) << multiplier
-		if (digit & 128) == 0 {
-			break
-		}
-		multiplier += 7
-	}
-	return int(rLength)
-}

+ 0 - 44
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/pingreq.go

@@ -1,44 +0,0 @@
-package packets
-
-import (
-	"fmt"
-	"github.com/pborman/uuid"
-	"io"
-)
-
-//PingreqPacket is an internal representation of the fields of the
-//Pingreq MQTT packet
-type PingreqPacket struct {
-	FixedHeader
-	uuid uuid.UUID
-}
-
-func (pr *PingreqPacket) String() string {
-	str := fmt.Sprintf("%s", pr.FixedHeader)
-	return str
-}
-
-func (pr *PingreqPacket) Write(w io.Writer) error {
-	packet := pr.FixedHeader.pack()
-	_, err := packet.WriteTo(w)
-
-	return err
-}
-
-//Unpack decodes the details of a ControlPacket after the fixed
-//header has been read
-func (pr *PingreqPacket) Unpack(b io.Reader) {
-}
-
-//Details returns a Details struct containing the Qos and
-//MessageID of this ControlPacket
-func (pr *PingreqPacket) Details() Details {
-	return Details{Qos: 0, MessageID: 0}
-}
-
-//UUID returns the unique ID assigned to the ControlPacket when
-//it was originally received. Note: this is not related to the
-//MessageID field for MQTT packets
-func (pr *PingreqPacket) UUID() uuid.UUID {
-	return pr.uuid
-}

+ 0 - 44
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/pingresp.go

@@ -1,44 +0,0 @@
-package packets
-
-import (
-	"fmt"
-	"github.com/pborman/uuid"
-	"io"
-)
-
-//PingrespPacket is an internal representation of the fields of the
-//Pingresp MQTT packet
-type PingrespPacket struct {
-	FixedHeader
-	uuid uuid.UUID
-}
-
-func (pr *PingrespPacket) String() string {
-	str := fmt.Sprintf("%s", pr.FixedHeader)
-	return str
-}
-
-func (pr *PingrespPacket) Write(w io.Writer) error {
-	packet := pr.FixedHeader.pack()
-	_, err := packet.WriteTo(w)
-
-	return err
-}
-
-//Unpack decodes the details of a ControlPacket after the fixed
-//header has been read
-func (pr *PingrespPacket) Unpack(b io.Reader) {
-}
-
-//Details returns a Details struct containing the Qos and
-//MessageID of this ControlPacket
-func (pr *PingrespPacket) Details() Details {
-	return Details{Qos: 0, MessageID: 0}
-}
-
-//UUID returns the unique ID assigned to the ControlPacket when
-//it was originally received. Note: this is not related to the
-//MessageID field for MQTT packets
-func (pr *PingrespPacket) UUID() uuid.UUID {
-	return pr.uuid
-}

+ 0 - 50
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/puback.go

@@ -1,50 +0,0 @@
-package packets
-
-import (
-	"fmt"
-	"github.com/pborman/uuid"
-	"io"
-)
-
-//PubackPacket is an internal representation of the fields of the
-//Puback MQTT packet
-type PubackPacket struct {
-	FixedHeader
-	MessageID uint16
-	uuid      uuid.UUID
-}
-
-func (pa *PubackPacket) String() string {
-	str := fmt.Sprintf("%s\n", pa.FixedHeader)
-	str += fmt.Sprintf("messageID: %d", pa.MessageID)
-	return str
-}
-
-func (pa *PubackPacket) Write(w io.Writer) error {
-	var err error
-	pa.FixedHeader.RemainingLength = 2
-	packet := pa.FixedHeader.pack()
-	packet.Write(encodeUint16(pa.MessageID))
-	_, err = packet.WriteTo(w)
-
-	return err
-}
-
-//Unpack decodes the details of a ControlPacket after the fixed
-//header has been read
-func (pa *PubackPacket) Unpack(b io.Reader) {
-	pa.MessageID = decodeUint16(b)
-}
-
-//Details returns a Details struct containing the Qos and
-//MessageID of this ControlPacket
-func (pa *PubackPacket) Details() Details {
-	return Details{Qos: pa.Qos, MessageID: pa.MessageID}
-}
-
-//UUID returns the unique ID assigned to the ControlPacket when
-//it was originally received. Note: this is not related to the
-//MessageID field for MQTT packets
-func (pa *PubackPacket) UUID() uuid.UUID {
-	return pa.uuid
-}

+ 0 - 50
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/pubcomp.go

@@ -1,50 +0,0 @@
-package packets
-
-import (
-	"fmt"
-	"github.com/pborman/uuid"
-	"io"
-)
-
-//PubcompPacket is an internal representation of the fields of the
-//Pubcomp MQTT packet
-type PubcompPacket struct {
-	FixedHeader
-	MessageID uint16
-	uuid      uuid.UUID
-}
-
-func (pc *PubcompPacket) String() string {
-	str := fmt.Sprintf("%s\n", pc.FixedHeader)
-	str += fmt.Sprintf("MessageID: %d", pc.MessageID)
-	return str
-}
-
-func (pc *PubcompPacket) Write(w io.Writer) error {
-	var err error
-	pc.FixedHeader.RemainingLength = 2
-	packet := pc.FixedHeader.pack()
-	packet.Write(encodeUint16(pc.MessageID))
-	_, err = packet.WriteTo(w)
-
-	return err
-}
-
-//Unpack decodes the details of a ControlPacket after the fixed
-//header has been read
-func (pc *PubcompPacket) Unpack(b io.Reader) {
-	pc.MessageID = decodeUint16(b)
-}
-
-//Details returns a Details struct containing the Qos and
-//MessageID of this ControlPacket
-func (pc *PubcompPacket) Details() Details {
-	return Details{Qos: pc.Qos, MessageID: pc.MessageID}
-}
-
-//UUID returns the unique ID assigned to the ControlPacket when
-//it was originally received. Note: this is not related to the
-//MessageID field for MQTT packets
-func (pc *PubcompPacket) UUID() uuid.UUID {
-	return pc.uuid
-}

+ 0 - 82
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/publish.go

@@ -1,82 +0,0 @@
-package packets
-
-import (
-	"bytes"
-	"fmt"
-	"github.com/pborman/uuid"
-	"io"
-)
-
-//PublishPacket is an internal representation of the fields of the
-//Publish MQTT packet
-type PublishPacket struct {
-	FixedHeader
-	TopicName string
-	MessageID uint16
-	Payload   []byte
-	uuid      uuid.UUID
-}
-
-func (p *PublishPacket) String() string {
-	str := fmt.Sprintf("%s\n", p.FixedHeader)
-	str += fmt.Sprintf("topicName: %s MessageID: %d\n", p.TopicName, p.MessageID)
-	str += fmt.Sprintf("payload: %s\n", string(p.Payload))
-	return str
-}
-
-func (p *PublishPacket) Write(w io.Writer) error {
-	var body bytes.Buffer
-	var err error
-
-	body.Write(encodeString(p.TopicName))
-	if p.Qos > 0 {
-		body.Write(encodeUint16(p.MessageID))
-	}
-	p.FixedHeader.RemainingLength = body.Len() + len(p.Payload)
-	packet := p.FixedHeader.pack()
-	packet.Write(body.Bytes())
-	packet.Write(p.Payload)
-	_, err = w.Write(packet.Bytes())
-
-	return err
-}
-
-//Unpack decodes the details of a ControlPacket after the fixed
-//header has been read
-func (p *PublishPacket) Unpack(b io.Reader) {
-	var payloadLength = p.FixedHeader.RemainingLength
-	p.TopicName = decodeString(b)
-	if p.Qos > 0 {
-		p.MessageID = decodeUint16(b)
-		payloadLength -= len(p.TopicName) + 4
-	} else {
-		payloadLength -= len(p.TopicName) + 2
-	}
-	p.Payload = make([]byte, payloadLength)
-	b.Read(p.Payload)
-}
-
-//Copy creates a new PublishPacket with the same topic and payload
-//but an empty fixed header, useful for when you want to deliver
-//a message with different properties such as Qos but the same
-//content
-func (p *PublishPacket) Copy() *PublishPacket {
-	newP := NewControlPacket(Publish).(*PublishPacket)
-	newP.TopicName = p.TopicName
-	newP.Payload = p.Payload
-
-	return newP
-}
-
-//Details returns a Details struct containing the Qos and
-//MessageID of this ControlPacket
-func (p *PublishPacket) Details() Details {
-	return Details{Qos: p.Qos, MessageID: p.MessageID}
-}
-
-//UUID returns the unique ID assigned to the ControlPacket when
-//it was originally received. Note: this is not related to the
-//MessageID field for MQTT packets
-func (p *PublishPacket) UUID() uuid.UUID {
-	return p.uuid
-}

+ 0 - 50
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/pubrec.go

@@ -1,50 +0,0 @@
-package packets
-
-import (
-	"fmt"
-	"github.com/pborman/uuid"
-	"io"
-)
-
-//PubrecPacket is an internal representation of the fields of the
-//Pubrec MQTT packet
-type PubrecPacket struct {
-	FixedHeader
-	MessageID uint16
-	uuid      uuid.UUID
-}
-
-func (pr *PubrecPacket) String() string {
-	str := fmt.Sprintf("%s\n", pr.FixedHeader)
-	str += fmt.Sprintf("MessageID: %d", pr.MessageID)
-	return str
-}
-
-func (pr *PubrecPacket) Write(w io.Writer) error {
-	var err error
-	pr.FixedHeader.RemainingLength = 2
-	packet := pr.FixedHeader.pack()
-	packet.Write(encodeUint16(pr.MessageID))
-	_, err = packet.WriteTo(w)
-
-	return err
-}
-
-//Unpack decodes the details of a ControlPacket after the fixed
-//header has been read
-func (pr *PubrecPacket) Unpack(b io.Reader) {
-	pr.MessageID = decodeUint16(b)
-}
-
-//Details returns a Details struct containing the Qos and
-//MessageID of this ControlPacket
-func (pr *PubrecPacket) Details() Details {
-	return Details{Qos: pr.Qos, MessageID: pr.MessageID}
-}
-
-//UUID returns the unique ID assigned to the ControlPacket when
-//it was originally received. Note: this is not related to the
-//MessageID field for MQTT packets
-func (pr *PubrecPacket) UUID() uuid.UUID {
-	return pr.uuid
-}

+ 0 - 50
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/pubrel.go

@@ -1,50 +0,0 @@
-package packets
-
-import (
-	"fmt"
-	"github.com/pborman/uuid"
-	"io"
-)
-
-//PubrelPacket is an internal representation of the fields of the
-//Pubrel MQTT packet
-type PubrelPacket struct {
-	FixedHeader
-	MessageID uint16
-	uuid      uuid.UUID
-}
-
-func (pr *PubrelPacket) String() string {
-	str := fmt.Sprintf("%s\n", pr.FixedHeader)
-	str += fmt.Sprintf("MessageID: %d", pr.MessageID)
-	return str
-}
-
-func (pr *PubrelPacket) Write(w io.Writer) error {
-	var err error
-	pr.FixedHeader.RemainingLength = 2
-	packet := pr.FixedHeader.pack()
-	packet.Write(encodeUint16(pr.MessageID))
-	_, err = packet.WriteTo(w)
-
-	return err
-}
-
-//Unpack decodes the details of a ControlPacket after the fixed
-//header has been read
-func (pr *PubrelPacket) Unpack(b io.Reader) {
-	pr.MessageID = decodeUint16(b)
-}
-
-//Details returns a Details struct containing the Qos and
-//MessageID of this ControlPacket
-func (pr *PubrelPacket) Details() Details {
-	return Details{Qos: pr.Qos, MessageID: pr.MessageID}
-}
-
-//UUID returns the unique ID assigned to the ControlPacket when
-//it was originally received. Note: this is not related to the
-//MessageID field for MQTT packets
-func (pr *PubrelPacket) UUID() uuid.UUID {
-	return pr.uuid
-}

+ 0 - 58
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/suback.go

@@ -1,58 +0,0 @@
-package packets
-
-import (
-	"bytes"
-	"fmt"
-	"github.com/pborman/uuid"
-	"io"
-)
-
-//SubackPacket is an internal representation of the fields of the
-//Suback MQTT packet
-type SubackPacket struct {
-	FixedHeader
-	MessageID   uint16
-	GrantedQoss []byte
-	uuid        uuid.UUID
-}
-
-func (sa *SubackPacket) String() string {
-	str := fmt.Sprintf("%s\n", sa.FixedHeader)
-	str += fmt.Sprintf("MessageID: %d", sa.MessageID)
-	return str
-}
-
-func (sa *SubackPacket) Write(w io.Writer) error {
-	var body bytes.Buffer
-	var err error
-	body.Write(encodeUint16(sa.MessageID))
-	body.Write(sa.GrantedQoss)
-	sa.FixedHeader.RemainingLength = body.Len()
-	packet := sa.FixedHeader.pack()
-	packet.Write(body.Bytes())
-	_, err = packet.WriteTo(w)
-
-	return err
-}
-
-//Unpack decodes the details of a ControlPacket after the fixed
-//header has been read
-func (sa *SubackPacket) Unpack(b io.Reader) {
-	var qosBuffer bytes.Buffer
-	sa.MessageID = decodeUint16(b)
-	qosBuffer.ReadFrom(b)
-	sa.GrantedQoss = qosBuffer.Bytes()
-}
-
-//Details returns a Details struct containing the Qos and
-//MessageID of this ControlPacket
-func (sa *SubackPacket) Details() Details {
-	return Details{Qos: 0, MessageID: sa.MessageID}
-}
-
-//UUID returns the unique ID assigned to the ControlPacket when
-//it was originally received. Note: this is not related to the
-//MessageID field for MQTT packets
-func (sa *SubackPacket) UUID() uuid.UUID {
-	return sa.uuid
-}

+ 0 - 68
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/subscribe.go

@@ -1,68 +0,0 @@
-package packets
-
-import (
-	"bytes"
-	"fmt"
-	"github.com/pborman/uuid"
-	"io"
-)
-
-//SubscribePacket is an internal representation of the fields of the
-//Subscribe MQTT packet
-type SubscribePacket struct {
-	FixedHeader
-	MessageID uint16
-	Topics    []string
-	Qoss      []byte
-	uuid      uuid.UUID
-}
-
-func (s *SubscribePacket) String() string {
-	str := fmt.Sprintf("%s\n", s.FixedHeader)
-	str += fmt.Sprintf("MessageID: %d topics: %s", s.MessageID, s.Topics)
-	return str
-}
-
-func (s *SubscribePacket) Write(w io.Writer) error {
-	var body bytes.Buffer
-	var err error
-
-	body.Write(encodeUint16(s.MessageID))
-	for i, topic := range s.Topics {
-		body.Write(encodeString(topic))
-		body.WriteByte(s.Qoss[i])
-	}
-	s.FixedHeader.RemainingLength = body.Len()
-	packet := s.FixedHeader.pack()
-	packet.Write(body.Bytes())
-	_, err = packet.WriteTo(w)
-
-	return err
-}
-
-//Unpack decodes the details of a ControlPacket after the fixed
-//header has been read
-func (s *SubscribePacket) Unpack(b io.Reader) {
-	s.MessageID = decodeUint16(b)
-	payloadLength := s.FixedHeader.RemainingLength - 2
-	for payloadLength > 0 {
-		topic := decodeString(b)
-		s.Topics = append(s.Topics, topic)
-		qos := decodeByte(b)
-		s.Qoss = append(s.Qoss, qos)
-		payloadLength -= 2 + len(topic) + 1 //2 bytes of string length, plus string, plus 1 byte for Qos
-	}
-}
-
-//Details returns a Details struct containing the Qos and
-//MessageID of this ControlPacket
-func (s *SubscribePacket) Details() Details {
-	return Details{Qos: 1, MessageID: s.MessageID}
-}
-
-//UUID returns the unique ID assigned to the ControlPacket when
-//it was originally received. Note: this is not related to the
-//MessageID field for MQTT packets
-func (s *SubscribePacket) UUID() uuid.UUID {
-	return s.uuid
-}

+ 0 - 50
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/unsuback.go

@@ -1,50 +0,0 @@
-package packets
-
-import (
-	"fmt"
-	"github.com/pborman/uuid"
-	"io"
-)
-
-//UnsubackPacket is an internal representation of the fields of the
-//Unsuback MQTT packet
-type UnsubackPacket struct {
-	FixedHeader
-	MessageID uint16
-	uuid      uuid.UUID
-}
-
-func (ua *UnsubackPacket) String() string {
-	str := fmt.Sprintf("%s\n", ua.FixedHeader)
-	str += fmt.Sprintf("MessageID: %d", ua.MessageID)
-	return str
-}
-
-func (ua *UnsubackPacket) Write(w io.Writer) error {
-	var err error
-	ua.FixedHeader.RemainingLength = 2
-	packet := ua.FixedHeader.pack()
-	packet.Write(encodeUint16(ua.MessageID))
-	_, err = packet.WriteTo(w)
-
-	return err
-}
-
-//Unpack decodes the details of a ControlPacket after the fixed
-//header has been read
-func (ua *UnsubackPacket) Unpack(b io.Reader) {
-	ua.MessageID = decodeUint16(b)
-}
-
-//Details returns a Details struct containing the Qos and
-//MessageID of this ControlPacket
-func (ua *UnsubackPacket) Details() Details {
-	return Details{Qos: 0, MessageID: ua.MessageID}
-}
-
-//UUID returns the unique ID assigned to the ControlPacket when
-//it was originally received. Note: this is not related to the
-//MessageID field for MQTT packets
-func (ua *UnsubackPacket) UUID() uuid.UUID {
-	return ua.uuid
-}

+ 0 - 61
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets/unsubscribe.go

@@ -1,61 +0,0 @@
-package packets
-
-import (
-	"bytes"
-	"fmt"
-	"github.com/pborman/uuid"
-	"io"
-)
-
-//UnsubscribePacket is an internal representation of the fields of the
-//Unsubscribe MQTT packet
-type UnsubscribePacket struct {
-	FixedHeader
-	MessageID uint16
-	Topics    []string
-	uuid      uuid.UUID
-}
-
-func (u *UnsubscribePacket) String() string {
-	str := fmt.Sprintf("%s\n", u.FixedHeader)
-	str += fmt.Sprintf("MessageID: %d", u.MessageID)
-	return str
-}
-
-func (u *UnsubscribePacket) Write(w io.Writer) error {
-	var body bytes.Buffer
-	var err error
-	body.Write(encodeUint16(u.MessageID))
-	for _, topic := range u.Topics {
-		body.Write(encodeString(topic))
-	}
-	u.FixedHeader.RemainingLength = body.Len()
-	packet := u.FixedHeader.pack()
-	packet.Write(body.Bytes())
-	_, err = packet.WriteTo(w)
-
-	return err
-}
-
-//Unpack decodes the details of a ControlPacket after the fixed
-//header has been read
-func (u *UnsubscribePacket) Unpack(b io.Reader) {
-	u.MessageID = decodeUint16(b)
-	var topic string
-	for topic = decodeString(b); topic != ""; topic = decodeString(b) {
-		u.Topics = append(u.Topics, topic)
-	}
-}
-
-//Details returns a Details struct containing the Qos and
-//MessageID of this ControlPacket
-func (u *UnsubscribePacket) Details() Details {
-	return Details{Qos: 1, MessageID: u.MessageID}
-}
-
-//UUID returns the unique ID assigned to the ControlPacket when
-//it was originally received. Note: this is not related to the
-//MessageID field for MQTT packets
-func (u *UnsubscribePacket) UUID() uuid.UUID {
-	return u.uuid
-}

+ 0 - 73
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/ping.go

@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2013 IBM Corp.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Seth Hoenig
- *    Allan Stockdill-Mander
- *    Mike Robertson
- */
-
-package mqtt
-
-import (
-	"errors"
-	"git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets"
-	"sync"
-	"time"
-)
-
-type lastcontact struct {
-	sync.Mutex
-	lasttime time.Time
-}
-
-func (l *lastcontact) update() {
-	l.Lock()
-	defer l.Unlock()
-	l.lasttime = time.Now()
-
-}
-
-func (l *lastcontact) get() time.Time {
-	l.Lock()
-	defer l.Unlock()
-	return l.lasttime
-}
-
-func keepalive(c *Client) {
-	DEBUG.Println(PNG, "keepalive starting")
-	c.pingOutstanding = false
-
-	for {
-		select {
-		case <-c.stop:
-			DEBUG.Println(PNG, "keepalive stopped")
-			c.workers.Done()
-			return
-		default:
-			last := uint(time.Since(c.lastContact.get()).Seconds())
-			//DEBUG.Printf("%s last contact: %d (timeout: %d)", PNG, last, uint(c.options.KeepAlive.Seconds()))
-			if last > uint(c.options.KeepAlive.Seconds()) {
-				if !c.pingOutstanding {
-					DEBUG.Println(PNG, "keepalive sending ping")
-					ping := packets.NewControlPacket(packets.Pingreq).(*packets.PingreqPacket)
-					c.pingOutstanding = true
-					//We don't want to wait behind large messages being sent, the Write call
-					//will block until it it able to send the packet.
-					ping.Write(c.conn)
-				} else {
-					CRITICAL.Println(PNG, "pingresp not received, disconnecting")
-					c.workers.Done()
-					c.internalConnLost(errors.New("pingresp not received, disconnecting"))
-					return
-				}
-			}
-			time.Sleep(1 * time.Second)
-		}
-	}
-}

+ 0 - 162
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/router.go

@@ -1,162 +0,0 @@
-/*
- * Copyright (c) 2013 IBM Corp.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Seth Hoenig
- *    Allan Stockdill-Mander
- *    Mike Robertson
- */
-
-package mqtt
-
-import (
-	"container/list"
-	"git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets"
-	"strings"
-	"sync"
-)
-
-// route is a type which associates MQTT Topic strings with a
-// callback to be executed upon the arrival of a message associated
-// with a subscription to that topic.
-type route struct {
-	topic    string
-	callback MessageHandler
-}
-
-// match takes a slice of strings which represent the route being tested having been split on '/'
-// separators, and a slice of strings representing the topic string in the published message, similarly
-// split.
-// The function determines if the topic string matches the route according to the MQTT topic rules
-// and returns a boolean of the outcome
-func match(route []string, topic []string) bool {
-	if len(route) == 0 {
-		if len(topic) == 0 {
-			return true
-		}
-		return false
-	}
-
-	if len(topic) == 0 {
-		if route[0] == "#" {
-			return true
-		}
-		return false
-	}
-
-	if route[0] == "#" {
-		return true
-	}
-
-	if (route[0] == "+") || (route[0] == topic[0]) {
-		return match(route[1:], topic[1:])
-	}
-
-	return false
-}
-
-func routeIncludesTopic(route, topic string) bool {
-	return match(strings.Split(route, "/"), strings.Split(topic, "/"))
-}
-
-// match takes the topic string of the published message and does a basic compare to the
-// string of the current Route, if they match it returns true
-func (r *route) match(topic string) bool {
-	return r.topic == topic || routeIncludesTopic(r.topic, topic)
-}
-
-type router struct {
-	sync.RWMutex
-	routes         *list.List
-	defaultHandler MessageHandler
-	messages       chan *packets.PublishPacket
-	stop           chan bool
-}
-
-// newRouter returns a new instance of a Router and channel which can be used to tell the Router
-// to stop
-func newRouter() (*router, chan bool) {
-	router := &router{routes: list.New(), messages: make(chan *packets.PublishPacket), stop: make(chan bool)}
-	stop := router.stop
-	return router, stop
-}
-
-// addRoute takes a topic string and MessageHandler callback. It looks in the current list of
-// routes to see if there is already a matching Route. If there is it replaces the current
-// callback with the new one. If not it add a new entry to the list of Routes.
-func (r *router) addRoute(topic string, callback MessageHandler) {
-	r.Lock()
-	defer r.Unlock()
-	for e := r.routes.Front(); e != nil; e = e.Next() {
-		if e.Value.(*route).match(topic) {
-			r := e.Value.(*route)
-			r.callback = callback
-			return
-		}
-	}
-	r.routes.PushBack(&route{topic: topic, callback: callback})
-}
-
-// deleteRoute takes a route string, looks for a matching Route in the list of Routes. If
-// found it removes the Route from the list.
-func (r *router) deleteRoute(topic string) {
-	r.Lock()
-	defer r.Unlock()
-	for e := r.routes.Front(); e != nil; e = e.Next() {
-		if e.Value.(*route).match(topic) {
-			r.routes.Remove(e)
-			return
-		}
-	}
-}
-
-// setDefaultHandler assigns a default callback that will be called if no matching Route
-// is found for an incoming Publish.
-func (r *router) setDefaultHandler(handler MessageHandler) {
-	r.defaultHandler = handler
-}
-
-// matchAndDispatch takes a channel of Message pointers as input and starts a go routine that
-// takes messages off the channel, matches them against the internal route list and calls the
-// associated callback (or the defaultHandler, if one exists and no other route matched). If
-// anything is sent down the stop channel the function will end.
-func (r *router) matchAndDispatch(messages <-chan *packets.PublishPacket, order bool, client *Client) {
-	go func() {
-		for {
-			select {
-			case message := <-messages:
-				sent := false
-				r.RLock()
-				for e := r.routes.Front(); e != nil; e = e.Next() {
-					if e.Value.(*route).match(message.TopicName) {
-						if order {
-							r.RUnlock()
-							e.Value.(*route).callback(client, messageFromPublish(message))
-							r.RLock()
-						} else {
-							go e.Value.(*route).callback(client, messageFromPublish(message))
-						}
-						sent = true
-					}
-				}
-				r.RUnlock()
-				if !sent && r.defaultHandler != nil {
-					if order {
-						r.RLock()
-						r.defaultHandler(client, messageFromPublish(message))
-						r.RUnlock()
-					} else {
-						go r.defaultHandler(client, messageFromPublish(message))
-					}
-				}
-			case <-r.stop:
-				return
-			}
-		}
-	}()
-}

+ 0 - 125
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/store.go

@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2013 IBM Corp.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Seth Hoenig
- *    Allan Stockdill-Mander
- *    Mike Robertson
- */
-
-package mqtt
-
-import (
-	"fmt"
-	"git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets"
-	"strconv"
-)
-
-const (
-	inboundPrefix  = "i."
-	outboundPrefix = "o."
-)
-
-// Store is an interface which can be used to provide implementations
-// for message persistence.
-// Because we may have to store distinct messages with the same
-// message ID, we need a unique key for each message. This is
-// possible by prepending "i." or "o." to each message id
-type Store interface {
-	Open()
-	Put(string, packets.ControlPacket)
-	Get(string) packets.ControlPacket
-	All() []string
-	Del(string)
-	Close()
-	Reset()
-}
-
-// A key MUST have the form "X.[messageid]"
-// where X is 'i' or 'o'
-func mIDFromKey(key string) uint16 {
-	s := key[2:]
-	i, err := strconv.Atoi(s)
-	chkerr(err)
-	return uint16(i)
-}
-
-// Return a string of the form "i.[id]"
-func inboundKeyFromMID(id uint16) string {
-	return fmt.Sprintf("%s%d", inboundPrefix, id)
-}
-
-// Return a string of the form "o.[id]"
-func outboundKeyFromMID(id uint16) string {
-	return fmt.Sprintf("%s%d", outboundPrefix, id)
-}
-
-// govern which outgoing messages are persisted
-func persistOutbound(s Store, m packets.ControlPacket) {
-	switch m.Details().Qos {
-	case 0:
-		switch m.(type) {
-		case *packets.PubackPacket, *packets.PubcompPacket:
-			// Sending puback. delete matching publish
-			// from ibound
-			s.Del(inboundKeyFromMID(m.Details().MessageID))
-		}
-	case 1:
-		switch m.(type) {
-		case *packets.PublishPacket, *packets.PubrelPacket, *packets.SubscribePacket, *packets.UnsubscribePacket:
-			// Sending publish. store in obound
-			// until puback received
-			s.Put(outboundKeyFromMID(m.Details().MessageID), m)
-		default:
-			chkcond(false)
-		}
-	case 2:
-		switch m.(type) {
-		case *packets.PublishPacket:
-			// Sending publish. store in obound
-			// until pubrel received
-			s.Put(outboundKeyFromMID(m.Details().MessageID), m)
-		default:
-			chkcond(false)
-		}
-	}
-}
-
-// govern which incoming messages are persisted
-func persistInbound(s Store, m packets.ControlPacket) {
-	switch m.Details().Qos {
-	case 0:
-		switch m.(type) {
-		case *packets.PubackPacket, *packets.SubackPacket, *packets.UnsubackPacket, *packets.PubcompPacket:
-			// Received a puback. delete matching publish
-			// from obound
-			s.Del(outboundKeyFromMID(m.Details().MessageID))
-		case *packets.PublishPacket, *packets.PubrecPacket, *packets.PingrespPacket, *packets.ConnackPacket:
-		default:
-			chkcond(false)
-		}
-	case 1:
-		switch m.(type) {
-		case *packets.PublishPacket, *packets.PubrelPacket:
-			// Received a publish. store it in ibound
-			// until puback sent
-			s.Put(inboundKeyFromMID(m.Details().MessageID), m)
-		default:
-			chkcond(false)
-		}
-	case 2:
-		switch m.(type) {
-		case *packets.PublishPacket:
-			// Received a publish. store it in ibound
-			// until pubrel received
-			s.Put(inboundKeyFromMID(m.Details().MessageID), m)
-		default:
-			chkcond(false)
-		}
-	}
-}

+ 0 - 156
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/token.go

@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2014 IBM Corp.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Allan Stockdill-Mander
- */
-
-package mqtt
-
-import (
-	"git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/packets"
-	"sync"
-	"time"
-)
-
-//PacketAndToken is a struct that contains both a ControlPacket and a
-//Token. This struct is passed via channels between the client interface
-//code and the underlying code responsible for sending and receiving
-//MQTT messages.
-type PacketAndToken struct {
-	p packets.ControlPacket
-	t Token
-}
-
-//Token defines the interface for the tokens used to indicate when
-//actions have completed.
-type Token interface {
-	Wait() bool
-	WaitTimeout(time.Duration) bool
-	flowComplete()
-	Error() error
-}
-
-type baseToken struct {
-	m        sync.RWMutex
-	complete chan struct{}
-	ready    bool
-	err      error
-}
-
-// Wait will wait indefinitely for the Token to complete, ie the Publish
-// to be sent and confirmed receipt from the broker
-func (b *baseToken) Wait() bool {
-	b.m.Lock()
-	defer b.m.Unlock()
-	if !b.ready {
-		<-b.complete
-		b.ready = true
-	}
-	return b.ready
-}
-
-// WaitTimeout takes a time in ms to wait for the flow associated with the
-// Token to complete, returns true if it returned before the timeout or
-// returns false if the timeout occurred. In the case of a timeout the Token
-// does not have an error set in case the caller wishes to wait again
-func (b *baseToken) WaitTimeout(d time.Duration) bool {
-	b.m.Lock()
-	defer b.m.Unlock()
-	if !b.ready {
-		select {
-		case <-b.complete:
-			b.ready = true
-		case <-time.After(d):
-		}
-	}
-	return b.ready
-}
-
-func (b *baseToken) flowComplete() {
-	close(b.complete)
-}
-
-func (b *baseToken) Error() error {
-	b.m.RLock()
-	defer b.m.RUnlock()
-	return b.err
-}
-
-func newToken(tType byte) Token {
-	switch tType {
-	case packets.Connect:
-		return &ConnectToken{baseToken: baseToken{complete: make(chan struct{})}}
-	case packets.Subscribe:
-		return &SubscribeToken{baseToken: baseToken{complete: make(chan struct{})}, subResult: make(map[string]byte)}
-	case packets.Publish:
-		return &PublishToken{baseToken: baseToken{complete: make(chan struct{})}}
-	case packets.Unsubscribe:
-		return &UnsubscribeToken{baseToken: baseToken{complete: make(chan struct{})}}
-	case packets.Disconnect:
-		return &DisconnectToken{baseToken: baseToken{complete: make(chan struct{})}}
-	}
-	return nil
-}
-
-//ConnectToken is an extension of Token containing the extra fields
-//required to provide information about calls to Connect()
-type ConnectToken struct {
-	baseToken
-	returnCode byte
-}
-
-//ReturnCode returns the acknowlegement code in the connack sent
-//in response to a Connect()
-func (c *ConnectToken) ReturnCode() byte {
-	c.m.RLock()
-	defer c.m.RUnlock()
-	return c.returnCode
-}
-
-//PublishToken is an extension of Token containing the extra fields
-//required to provide information about calls to Publish()
-type PublishToken struct {
-	baseToken
-	messageID uint16
-}
-
-//MessageID returns the MQTT message ID that was assigned to the
-//Publish packet when it was sent to the broker
-func (p *PublishToken) MessageID() uint16 {
-	return p.messageID
-}
-
-//SubscribeToken is an extension of Token containing the extra fields
-//required to provide information about calls to Subscribe()
-type SubscribeToken struct {
-	baseToken
-	subs      []string
-	subResult map[string]byte
-}
-
-//Result returns a map of topics that were subscribed to along with
-//the matching return code from the broker. This is either the Qos
-//value of the subscription or an error code.
-func (s *SubscribeToken) Result() map[string]byte {
-	s.m.RLock()
-	defer s.m.RUnlock()
-	return s.subResult
-}
-
-//UnsubscribeToken is an extension of Token containing the extra fields
-//required to provide information about calls to Unsubscribe()
-type UnsubscribeToken struct {
-	baseToken
-}
-
-//DisconnectToken is an extension of Token containing the extra fields
-//required to provide information about calls to Disconnect()
-type DisconnectToken struct {
-	baseToken
-}

+ 0 - 82
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/topic.go

@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2014 IBM Corp.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Seth Hoenig
- *    Allan Stockdill-Mander
- *    Mike Robertson
- */
-
-package mqtt
-
-import (
-	"errors"
-	"strings"
-)
-
-//InvalidQos is the error returned when an packet is to be sent
-//with an invalid Qos value
-var ErrInvalidQos = errors.New("Invalid QoS")
-
-//InvalidTopicEmptyString is the error returned when a topic string
-//is passed in that is 0 length
-var ErrInvalidTopicEmptyString = errors.New("Invalid Topic; empty string")
-
-//InvalidTopicMultilevel is the error returned when a topic string
-//is passed in that has the multi level wildcard in any position but
-//the last
-var ErrInvalidTopicMultilevel = errors.New("Invalid Topic; multi-level wildcard must be last level")
-
-// Topic Names and Topic Filters
-// The MQTT v3.1.1 spec clarifies a number of ambiguities with regard
-// to the validity of Topic strings.
-// - A Topic must be between 1 and 65535 bytes.
-// - A Topic is case sensitive.
-// - A Topic may contain whitespace.
-// - A Topic containing a leading forward slash is different than a Topic without.
-// - A Topic may be "/" (two levels, both empty string).
-// - A Topic must be UTF-8 encoded.
-// - A Topic may contain any number of levels.
-// - A Topic may contain an empty level (two forward slashes in a row).
-// - A TopicName may not contain a wildcard.
-// - A TopicFilter may only have a # (multi-level) wildcard as the last level.
-// - A TopicFilter may contain any number of + (single-level) wildcards.
-// - A TopicFilter with a # will match the absense of a level
-//     Example:  a subscription to "foo/#" will match messages published to "foo".
-
-func validateSubscribeMap(subs map[string]byte) ([]string, []byte, error) {
-	var topics []string
-	var qoss []byte
-	for topic, qos := range subs {
-		if err := validateTopicAndQos(topic, qos); err != nil {
-			return nil, nil, err
-		}
-		topics = append(topics, topic)
-		qoss = append(qoss, qos)
-	}
-
-	return topics, qoss, nil
-}
-
-func validateTopicAndQos(topic string, qos byte) error {
-	if len(topic) == 0 {
-		return ErrInvalidTopicEmptyString
-	}
-
-	levels := strings.Split(topic, "/")
-	for i, level := range levels {
-		if level == "#" && i != len(levels)-1 {
-			return ErrInvalidTopicMultilevel
-		}
-	}
-
-	if qos < 0 || qos > 2 {
-		return ErrInvalidQos
-	}
-	return nil
-}

+ 0 - 36
vendor/git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git/trace.go

@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2013 IBM Corp.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Seth Hoenig
- *    Allan Stockdill-Mander
- *    Mike Robertson
- */
-
-package mqtt
-
-import (
-	"io/ioutil"
-	"log"
-)
-
-// Internal levels of library output that are initialised to not print
-// anything but can be overridden by programmer
-var (
-	ERROR    *log.Logger
-	CRITICAL *log.Logger
-	WARN     *log.Logger
-	DEBUG    *log.Logger
-)
-
-func init() {
-	ERROR = log.New(ioutil.Discard, "", 0)
-	CRITICAL = log.New(ioutil.Discard, "", 0)
-	WARN = log.New(ioutil.Discard, "", 0)
-	DEBUG = log.New(ioutil.Discard, "", 0)
-}

BIN
vendor/github.com/.DS_Store


+ 2 - 0
vendor/github.com/BurntSushi/toml/.gitignore

@@ -0,0 +1,2 @@
+/toml.test
+/toml-test

+ 0 - 3
vendor/github.com/BurntSushi/toml/COMPATIBLE

@@ -1,3 +0,0 @@
-Compatible with TOML version
-[v0.4.0](https://github.com/toml-lang/toml/blob/v0.4.0/versions/en/toml-v0.4.0.md)
-

+ 21 - 14
vendor/github.com/BurntSushi/toml/COPYING

@@ -1,14 +1,21 @@
-            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
-                    Version 2, December 2004
-
- Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
-
- Everyone is permitted to copy and distribute verbatim or modified
- copies of this license document, and changing it is allowed as long
- as the name is changed.
-
-            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. You just DO WHAT THE FUCK YOU WANT TO.
-
+The MIT License (MIT)
+
+Copyright (c) 2013 TOML authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 0 - 19
vendor/github.com/BurntSushi/toml/Makefile

@@ -1,19 +0,0 @@
-install:
-	go install ./...
-
-test: install
-	go test -v
-	toml-test toml-test-decoder
-	toml-test -encoder toml-test-encoder
-
-fmt:
-	gofmt -w *.go */*.go
-	colcheck *.go */*.go
-
-tags:
-	find ./ -name '*.go' -print0 | xargs -0 gotags > TAGS
-
-push:
-	git push origin master
-	git push github master
-

+ 120 - 0
vendor/github.com/BurntSushi/toml/README.md

@@ -0,0 +1,120 @@
+TOML stands for Tom's Obvious, Minimal Language. This Go package provides a
+reflection interface similar to Go's standard library `json` and `xml` packages.
+
+Compatible with TOML version [v1.0.0](https://toml.io/en/v1.0.0).
+
+Documentation: https://godocs.io/github.com/BurntSushi/toml
+
+See the [releases page](https://github.com/BurntSushi/toml/releases) for a
+changelog; this information is also in the git tag annotations (e.g. `git show
+v0.4.0`).
+
+This library requires Go 1.13 or newer; add it to your go.mod with:
+
+    % go get github.com/BurntSushi/toml@latest
+
+It also comes with a TOML validator CLI tool:
+
+    % go install github.com/BurntSushi/toml/cmd/tomlv@latest
+    % tomlv some-toml-file.toml
+
+### Examples
+For the simplest example, consider some TOML file as just a list of keys and
+values:
+
+```toml
+Age = 25
+Cats = [ "Cauchy", "Plato" ]
+Pi = 3.14
+Perfection = [ 6, 28, 496, 8128 ]
+DOB = 1987-07-05T05:45:00Z
+```
+
+Which can be decoded with:
+
+```go
+type Config struct {
+	Age        int
+	Cats       []string
+	Pi         float64
+	Perfection []int
+	DOB        time.Time
+}
+
+var conf Config
+_, err := toml.Decode(tomlData, &conf)
+```
+
+You can also use struct tags if your struct field name doesn't map to a TOML key
+value directly:
+
+```toml
+some_key_NAME = "wat"
+```
+
+```go
+type TOML struct {
+    ObscureKey string `toml:"some_key_NAME"`
+}
+```
+
+Beware that like other decoders **only exported fields** are considered when
+encoding and decoding; private fields are silently ignored.
+
+### Using the `Marshaler` and `encoding.TextUnmarshaler` interfaces
+Here's an example that automatically parses values in a `mail.Address`:
+
+```toml
+contacts = [
+    "Donald Duck <donald@duckburg.com>",
+    "Scrooge McDuck <scrooge@duckburg.com>",
+]
+```
+
+Can be decoded with:
+
+```go
+// Create address type which satisfies the encoding.TextUnmarshaler interface.
+type address struct {
+	*mail.Address
+}
+
+func (a *address) UnmarshalText(text []byte) error {
+	var err error
+	a.Address, err = mail.ParseAddress(string(text))
+	return err
+}
+
+// Decode it.
+func decode() {
+	blob := `
+		contacts = [
+			"Donald Duck <donald@duckburg.com>",
+			"Scrooge McDuck <scrooge@duckburg.com>",
+		]
+	`
+
+	var contacts struct {
+		Contacts []address
+	}
+
+	_, err := toml.Decode(blob, &contacts)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	for _, c := range contacts.Contacts {
+		fmt.Printf("%#v\n", c.Address)
+	}
+
+	// Output:
+	// &mail.Address{Name:"Donald Duck", Address:"donald@duckburg.com"}
+	// &mail.Address{Name:"Scrooge McDuck", Address:"scrooge@duckburg.com"}
+}
+```
+
+To target TOML specifically you can implement `UnmarshalTOML` TOML interface in
+a similar way.
+
+### More complex usage
+See the [`_example/`](/_example) directory for a more complex example.

+ 299 - 206
vendor/github.com/BurntSushi/toml/decode.go

@@ -1,146 +1,188 @@
 package toml
 
 import (
+	"bytes"
+	"encoding"
+	"encoding/json"
 	"fmt"
 	"io"
 	"io/ioutil"
 	"math"
+	"os"
 	"reflect"
+	"strconv"
 	"strings"
 	"time"
 )
 
-func e(format string, args ...interface{}) error {
-	return fmt.Errorf("toml: "+format, args...)
-}
-
 // Unmarshaler is the interface implemented by objects that can unmarshal a
 // TOML description of themselves.
 type Unmarshaler interface {
 	UnmarshalTOML(interface{}) error
 }
 
-// Unmarshal decodes the contents of `p` in TOML format into a pointer `v`.
-func Unmarshal(p []byte, v interface{}) error {
-	_, err := Decode(string(p), v)
+// Unmarshal decodes the contents of data in TOML format into a pointer v.
+//
+// See [Decoder] for a description of the decoding process.
+func Unmarshal(data []byte, v interface{}) error {
+	_, err := NewDecoder(bytes.NewReader(data)).Decode(v)
 	return err
 }
 
+// Decode the TOML data in to the pointer v.
+//
+// See [Decoder] for a description of the decoding process.
+func Decode(data string, v interface{}) (MetaData, error) {
+	return NewDecoder(strings.NewReader(data)).Decode(v)
+}
+
+// DecodeFile reads the contents of a file and decodes it with [Decode].
+func DecodeFile(path string, v interface{}) (MetaData, error) {
+	fp, err := os.Open(path)
+	if err != nil {
+		return MetaData{}, err
+	}
+	defer fp.Close()
+	return NewDecoder(fp).Decode(v)
+}
+
 // Primitive is a TOML value that hasn't been decoded into a Go value.
-// When using the various `Decode*` functions, the type `Primitive` may
-// be given to any value, and its decoding will be delayed.
 //
-// A `Primitive` value can be decoded using the `PrimitiveDecode` function.
+// This type can be used for any value, which will cause decoding to be delayed.
+// You can use [PrimitiveDecode] to "manually" decode these values.
 //
-// The underlying representation of a `Primitive` value is subject to change.
-// Do not rely on it.
+// NOTE: The underlying representation of a `Primitive` value is subject to
+// change. Do not rely on it.
 //
-// N.B. Primitive values are still parsed, so using them will only avoid
-// the overhead of reflection. They can be useful when you don't know the
-// exact type of TOML data until run time.
+// NOTE: Primitive values are still parsed, so using them will only avoid the
+// overhead of reflection. They can be useful when you don't know the exact type
+// of TOML data until runtime.
 type Primitive struct {
 	undecoded interface{}
 	context   Key
 }
 
-// DEPRECATED!
-//
-// Use MetaData.PrimitiveDecode instead.
-func PrimitiveDecode(primValue Primitive, v interface{}) error {
-	md := MetaData{decoded: make(map[string]bool)}
-	return md.unify(primValue.undecoded, rvalue(v))
-}
+// The significand precision for float32 and float64 is 24 and 53 bits; this is
+// the range a natural number can be stored in a float without loss of data.
+const (
+	maxSafeFloat32Int = 16777215                // 2^24-1
+	maxSafeFloat64Int = int64(9007199254740991) // 2^53-1
+)
 
-// PrimitiveDecode is just like the other `Decode*` functions, except it
-// decodes a TOML value that has already been parsed. Valid primitive values
-// can *only* be obtained from values filled by the decoder functions,
-// including this method. (i.e., `v` may contain more `Primitive`
-// values.)
+// Decoder decodes TOML data.
 //
-// Meta data for primitive values is included in the meta data returned by
-// the `Decode*` functions with one exception: keys returned by the Undecoded
-// method will only reflect keys that were decoded. Namely, any keys hidden
-// behind a Primitive will be considered undecoded. Executing this method will
-// update the undecoded keys in the meta data. (See the example.)
-func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error {
-	md.context = primValue.context
-	defer func() { md.context = nil }()
-	return md.unify(primValue.undecoded, rvalue(v))
-}
-
-// Decode will decode the contents of `data` in TOML format into a pointer
-// `v`.
+// TOML tables correspond to Go structs or maps; they can be used
+// interchangeably, but structs offer better type safety.
 //
-// TOML hashes correspond to Go structs or maps. (Dealer's choice. They can be
-// used interchangeably.)
+// TOML table arrays correspond to either a slice of structs or a slice of maps.
 //
-// TOML arrays of tables correspond to either a slice of structs or a slice
-// of maps.
+// TOML datetimes correspond to [time.Time]. Local datetimes are parsed in the
+// local timezone.
 //
-// TOML datetimes correspond to Go `time.Time` values.
+// [time.Duration] types are treated as nanoseconds if the TOML value is an
+// integer, or they're parsed with time.ParseDuration() if they're strings.
 //
-// All other TOML types (float, string, int, bool and array) correspond
-// to the obvious Go types.
+// All other TOML types (float, string, int, bool and array) correspond to the
+// obvious Go types.
 //
-// An exception to the above rules is if a type implements the
-// encoding.TextUnmarshaler interface. In this case, any primitive TOML value
-// (floats, strings, integers, booleans and datetimes) will be converted to
-// a byte string and given to the value's UnmarshalText method. See the
-// Unmarshaler example for a demonstration with time duration strings.
+// An exception to the above rules is if a type implements the TextUnmarshaler
+// interface, in which case any primitive TOML value (floats, strings, integers,
+// booleans, datetimes) will be converted to a []byte and given to the value's
+// UnmarshalText method. See the Unmarshaler example for a demonstration with
+// email addresses.
 //
-// Key mapping
+// # Key mapping
 //
-// TOML keys can map to either keys in a Go map or field names in a Go
-// struct. The special `toml` struct tag may be used to map TOML keys to
-// struct fields that don't match the key name exactly. (See the example.)
-// A case insensitive match to struct names will be tried if an exact match
-// can't be found.
+// TOML keys can map to either keys in a Go map or field names in a Go struct.
+// The special `toml` struct tag can be used to map TOML keys to struct fields
+// that don't match the key name exactly (see the example). A case insensitive
+// match to struct names will be tried if an exact match can't be found.
 //
-// The mapping between TOML values and Go values is loose. That is, there
-// may exist TOML values that cannot be placed into your representation, and
-// there may be parts of your representation that do not correspond to
-// TOML values. This loose mapping can be made stricter by using the IsDefined
-// and/or Undecoded methods on the MetaData returned.
+// The mapping between TOML values and Go values is loose. That is, there may
+// exist TOML values that cannot be placed into your representation, and there
+// may be parts of your representation that do not correspond to TOML values.
+// This loose mapping can be made stricter by using the IsDefined and/or
+// Undecoded methods on the MetaData returned.
 //
-// This decoder will not handle cyclic types. If a cyclic type is passed,
-// `Decode` will not terminate.
-func Decode(data string, v interface{}) (MetaData, error) {
+// This decoder does not handle cyclic types. Decode will not terminate if a
+// cyclic type is passed.
+type Decoder struct {
+	r io.Reader
+}
+
+// NewDecoder creates a new Decoder.
+func NewDecoder(r io.Reader) *Decoder {
+	return &Decoder{r: r}
+}
+
+var (
+	unmarshalToml = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
+	unmarshalText = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
+	primitiveType = reflect.TypeOf((*Primitive)(nil)).Elem()
+)
+
+// Decode TOML data in to the pointer `v`.
+func (dec *Decoder) Decode(v interface{}) (MetaData, error) {
 	rv := reflect.ValueOf(v)
 	if rv.Kind() != reflect.Ptr {
-		return MetaData{}, e("Decode of non-pointer %s", reflect.TypeOf(v))
+		s := "%q"
+		if reflect.TypeOf(v) == nil {
+			s = "%v"
+		}
+
+		return MetaData{}, fmt.Errorf("toml: cannot decode to non-pointer "+s, reflect.TypeOf(v))
 	}
 	if rv.IsNil() {
-		return MetaData{}, e("Decode of nil %s", reflect.TypeOf(v))
-	}
-	p, err := parse(data)
-	if err != nil {
-		return MetaData{}, err
+		return MetaData{}, fmt.Errorf("toml: cannot decode to nil value of %q", reflect.TypeOf(v))
 	}
-	md := MetaData{
-		p.mapping, p.types, p.ordered,
-		make(map[string]bool, len(p.ordered)), nil,
+
+	// Check if this is a supported type: struct, map, interface{}, or something
+	// that implements UnmarshalTOML or UnmarshalText.
+	rv = indirect(rv)
+	rt := rv.Type()
+	if rv.Kind() != reflect.Struct && rv.Kind() != reflect.Map &&
+		!(rv.Kind() == reflect.Interface && rv.NumMethod() == 0) &&
+		!rt.Implements(unmarshalToml) && !rt.Implements(unmarshalText) {
+		return MetaData{}, fmt.Errorf("toml: cannot decode to type %s", rt)
 	}
-	return md, md.unify(p.mapping, indirect(rv))
-}
 
-// DecodeFile is just like Decode, except it will automatically read the
-// contents of the file at `fpath` and decode it for you.
-func DecodeFile(fpath string, v interface{}) (MetaData, error) {
-	bs, err := ioutil.ReadFile(fpath)
+	// TODO: parser should read from io.Reader? Or at the very least, make it
+	// read from []byte rather than string
+	data, err := ioutil.ReadAll(dec.r)
 	if err != nil {
 		return MetaData{}, err
 	}
-	return Decode(string(bs), v)
-}
 
-// DecodeReader is just like Decode, except it will consume all bytes
-// from the reader and decode it for you.
-func DecodeReader(r io.Reader, v interface{}) (MetaData, error) {
-	bs, err := ioutil.ReadAll(r)
+	p, err := parse(string(data))
 	if err != nil {
 		return MetaData{}, err
 	}
-	return Decode(string(bs), v)
+
+	md := MetaData{
+		mapping: p.mapping,
+		keyInfo: p.keyInfo,
+		keys:    p.ordered,
+		decoded: make(map[string]struct{}, len(p.ordered)),
+		context: nil,
+		data:    data,
+	}
+	return md, md.unify(p.mapping, rv)
+}
+
+// PrimitiveDecode is just like the other Decode* functions, except it decodes a
+// TOML value that has already been parsed. Valid primitive values can *only* be
+// obtained from values filled by the decoder functions, including this method.
+// (i.e., v may contain more [Primitive] values.)
+//
+// Meta data for primitive values is included in the meta data returned by the
+// Decode* functions with one exception: keys returned by the Undecoded method
+// will only reflect keys that were decoded. Namely, any keys hidden behind a
+// Primitive will be considered undecoded. Executing this method will update the
+// undecoded keys in the meta data. (See the example.)
+func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error {
+	md.context = primValue.context
+	defer func() { md.context = nil }()
+	return md.unify(primValue.undecoded, rvalue(v))
 }
 
 // unify performs a sort of type unification based on the structure of `rv`,
@@ -149,9 +191,9 @@ func DecodeReader(r io.Reader, v interface{}) (MetaData, error) {
 // Any type mismatch produces an error. Finding a type that we don't know
 // how to handle produces an unsupported type error.
 func (md *MetaData) unify(data interface{}, rv reflect.Value) error {
-
 	// Special case. Look for a `Primitive` value.
-	if rv.Type() == reflect.TypeOf((*Primitive)(nil)).Elem() {
+	// TODO: #76 would make this superfluous after implemented.
+	if rv.Type() == primitiveType {
 		// Save the undecoded data and the key context into the primitive
 		// value.
 		context := make(Key, len(md.context))
@@ -163,36 +205,24 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error {
 		return nil
 	}
 
-	// Special case. Unmarshaler Interface support.
-	if rv.CanAddr() {
-		if v, ok := rv.Addr().Interface().(Unmarshaler); ok {
-			return v.UnmarshalTOML(data)
-		}
+	rvi := rv.Interface()
+	if v, ok := rvi.(Unmarshaler); ok {
+		return v.UnmarshalTOML(data)
 	}
-
-	// Special case. Handle time.Time values specifically.
-	// TODO: Remove this code when we decide to drop support for Go 1.1.
-	// This isn't necessary in Go 1.2 because time.Time satisfies the encoding
-	// interfaces.
-	if rv.Type().AssignableTo(rvalue(time.Time{}).Type()) {
-		return md.unifyDatetime(data, rv)
-	}
-
-	// Special case. Look for a value satisfying the TextUnmarshaler interface.
-	if v, ok := rv.Interface().(TextUnmarshaler); ok {
+	if v, ok := rvi.(encoding.TextUnmarshaler); ok {
 		return md.unifyText(data, v)
 	}
-	// BUG(burntsushi)
+
+	// TODO:
 	// The behavior here is incorrect whenever a Go type satisfies the
-	// encoding.TextUnmarshaler interface but also corresponds to a TOML
-	// hash or array. In particular, the unmarshaler should only be applied
-	// to primitive TOML values. But at this point, it will be applied to
-	// all kinds of values and produce an incorrect error whenever those values
-	// are hashes or arrays (including arrays of tables).
+	// encoding.TextUnmarshaler interface but also corresponds to a TOML hash or
+	// array. In particular, the unmarshaler should only be applied to primitive
+	// TOML values. But at this point, it will be applied to all kinds of values
+	// and produce an incorrect error whenever those values are hashes or arrays
+	// (including arrays of tables).
 
 	k := rv.Kind()
 
-	// laziness
 	if k >= reflect.Int && k <= reflect.Uint64 {
 		return md.unifyInt(data, rv)
 	}
@@ -218,17 +248,14 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error {
 	case reflect.Bool:
 		return md.unifyBool(data, rv)
 	case reflect.Interface:
-		// we only support empty interfaces.
-		if rv.NumMethod() > 0 {
-			return e("unsupported type %s", rv.Type())
+		if rv.NumMethod() > 0 { /// Only empty interfaces are supported.
+			return md.e("unsupported type %s", rv.Type())
 		}
 		return md.unifyAnything(data, rv)
-	case reflect.Float32:
-		fallthrough
-	case reflect.Float64:
+	case reflect.Float32, reflect.Float64:
 		return md.unifyFloat64(data, rv)
 	}
-	return e("unsupported type %s", rv.Kind())
+	return md.e("unsupported type %s", rv.Kind())
 }
 
 func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error {
@@ -237,7 +264,7 @@ func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error {
 		if mapping == nil {
 			return nil
 		}
-		return e("type mismatch for %s: expected table but found %T",
+		return md.e("type mismatch for %s: expected table but found %T",
 			rv.Type().String(), mapping)
 	}
 
@@ -259,17 +286,18 @@ func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error {
 			for _, i := range f.index {
 				subv = indirect(subv.Field(i))
 			}
+
 			if isUnifiable(subv) {
-				md.decoded[md.context.add(key).String()] = true
+				md.decoded[md.context.add(key).String()] = struct{}{}
 				md.context = append(md.context, key)
-				if err := md.unify(datum, subv); err != nil {
+
+				err := md.unify(datum, subv)
+				if err != nil {
 					return err
 				}
 				md.context = md.context[0 : len(md.context)-1]
 			} else if f.name != "" {
-				// Bad user! No soup for you!
-				return e("cannot write unexported field %s.%s",
-					rv.Type().String(), f.name)
+				return md.e("cannot write unexported field %s.%s", rv.Type().String(), f.name)
 			}
 		}
 	}
@@ -277,28 +305,43 @@ func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error {
 }
 
 func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error {
+	keyType := rv.Type().Key().Kind()
+	if keyType != reflect.String && keyType != reflect.Interface {
+		return fmt.Errorf("toml: cannot decode to a map with non-string key type (%s in %q)",
+			keyType, rv.Type())
+	}
+
 	tmap, ok := mapping.(map[string]interface{})
 	if !ok {
 		if tmap == nil {
 			return nil
 		}
-		return badtype("map", mapping)
+		return md.badtype("map", mapping)
 	}
 	if rv.IsNil() {
 		rv.Set(reflect.MakeMap(rv.Type()))
 	}
 	for k, v := range tmap {
-		md.decoded[md.context.add(k).String()] = true
+		md.decoded[md.context.add(k).String()] = struct{}{}
 		md.context = append(md.context, k)
 
-		rvkey := indirect(reflect.New(rv.Type().Key()))
 		rvval := reflect.Indirect(reflect.New(rv.Type().Elem()))
-		if err := md.unify(v, rvval); err != nil {
+
+		err := md.unify(v, indirect(rvval))
+		if err != nil {
 			return err
 		}
 		md.context = md.context[0 : len(md.context)-1]
 
-		rvkey.SetString(k)
+		rvkey := indirect(reflect.New(rv.Type().Key()))
+
+		switch keyType {
+		case reflect.Interface:
+			rvkey.Set(reflect.ValueOf(k))
+		case reflect.String:
+			rvkey.SetString(k)
+		}
+
 		rv.SetMapIndex(rvkey, rvval)
 	}
 	return nil
@@ -310,12 +353,10 @@ func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error {
 		if !datav.IsValid() {
 			return nil
 		}
-		return badtype("slice", data)
+		return md.badtype("slice", data)
 	}
-	sliceLen := datav.Len()
-	if sliceLen != rv.Len() {
-		return e("expected array length %d; got TOML array of length %d",
-			rv.Len(), sliceLen)
+	if l := datav.Len(); l != rv.Len() {
+		return md.e("expected array length %d; got TOML array of length %d", rv.Len(), l)
 	}
 	return md.unifySliceArray(datav, rv)
 }
@@ -326,7 +367,7 @@ func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error {
 		if !datav.IsValid() {
 			return nil
 		}
-		return badtype("slice", data)
+		return md.badtype("slice", data)
 	}
 	n := datav.Len()
 	if rv.IsNil() || rv.Cap() < n {
@@ -337,37 +378,45 @@ func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error {
 }
 
 func (md *MetaData) unifySliceArray(data, rv reflect.Value) error {
-	sliceLen := data.Len()
-	for i := 0; i < sliceLen; i++ {
-		v := data.Index(i).Interface()
-		sliceval := indirect(rv.Index(i))
-		if err := md.unify(v, sliceval); err != nil {
+	l := data.Len()
+	for i := 0; i < l; i++ {
+		err := md.unify(data.Index(i).Interface(), indirect(rv.Index(i)))
+		if err != nil {
 			return err
 		}
 	}
 	return nil
 }
 
-func (md *MetaData) unifyDatetime(data interface{}, rv reflect.Value) error {
-	if _, ok := data.(time.Time); ok {
-		rv.Set(reflect.ValueOf(data))
+func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error {
+	_, ok := rv.Interface().(json.Number)
+	if ok {
+		if i, ok := data.(int64); ok {
+			rv.SetString(strconv.FormatInt(i, 10))
+		} else if f, ok := data.(float64); ok {
+			rv.SetString(strconv.FormatFloat(f, 'f', -1, 64))
+		} else {
+			return md.badtype("string", data)
+		}
 		return nil
 	}
-	return badtype("time.Time", data)
-}
 
-func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error {
 	if s, ok := data.(string); ok {
 		rv.SetString(s)
 		return nil
 	}
-	return badtype("string", data)
+	return md.badtype("string", data)
 }
 
 func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error {
+	rvk := rv.Kind()
+
 	if num, ok := data.(float64); ok {
-		switch rv.Kind() {
+		switch rvk {
 		case reflect.Float32:
+			if num < -math.MaxFloat32 || num > math.MaxFloat32 {
+				return md.parseErr(errParseRange{i: num, size: rvk.String()})
+			}
 			fallthrough
 		case reflect.Float64:
 			rv.SetFloat(num)
@@ -376,54 +425,60 @@ func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error {
 		}
 		return nil
 	}
-	return badtype("float", data)
+
+	if num, ok := data.(int64); ok {
+		if (rvk == reflect.Float32 && (num < -maxSafeFloat32Int || num > maxSafeFloat32Int)) ||
+			(rvk == reflect.Float64 && (num < -maxSafeFloat64Int || num > maxSafeFloat64Int)) {
+			return md.parseErr(errParseRange{i: num, size: rvk.String()})
+		}
+		rv.SetFloat(float64(num))
+		return nil
+	}
+
+	return md.badtype("float", data)
 }
 
 func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error {
-	if num, ok := data.(int64); ok {
-		if rv.Kind() >= reflect.Int && rv.Kind() <= reflect.Int64 {
-			switch rv.Kind() {
-			case reflect.Int, reflect.Int64:
-				// No bounds checking necessary.
-			case reflect.Int8:
-				if num < math.MinInt8 || num > math.MaxInt8 {
-					return e("value %d is out of range for int8", num)
-				}
-			case reflect.Int16:
-				if num < math.MinInt16 || num > math.MaxInt16 {
-					return e("value %d is out of range for int16", num)
-				}
-			case reflect.Int32:
-				if num < math.MinInt32 || num > math.MaxInt32 {
-					return e("value %d is out of range for int32", num)
-				}
+	_, ok := rv.Interface().(time.Duration)
+	if ok {
+		// Parse as string duration, and fall back to regular integer parsing
+		// (as nanosecond) if this is not a string.
+		if s, ok := data.(string); ok {
+			dur, err := time.ParseDuration(s)
+			if err != nil {
+				return md.parseErr(errParseDuration{s})
 			}
-			rv.SetInt(num)
-		} else if rv.Kind() >= reflect.Uint && rv.Kind() <= reflect.Uint64 {
-			unum := uint64(num)
-			switch rv.Kind() {
-			case reflect.Uint, reflect.Uint64:
-				// No bounds checking necessary.
-			case reflect.Uint8:
-				if num < 0 || unum > math.MaxUint8 {
-					return e("value %d is out of range for uint8", num)
-				}
-			case reflect.Uint16:
-				if num < 0 || unum > math.MaxUint16 {
-					return e("value %d is out of range for uint16", num)
-				}
-			case reflect.Uint32:
-				if num < 0 || unum > math.MaxUint32 {
-					return e("value %d is out of range for uint32", num)
-				}
-			}
-			rv.SetUint(unum)
-		} else {
-			panic("unreachable")
+			rv.SetInt(int64(dur))
+			return nil
 		}
-		return nil
 	}
-	return badtype("integer", data)
+
+	num, ok := data.(int64)
+	if !ok {
+		return md.badtype("integer", data)
+	}
+
+	rvk := rv.Kind()
+	switch {
+	case rvk >= reflect.Int && rvk <= reflect.Int64:
+		if (rvk == reflect.Int8 && (num < math.MinInt8 || num > math.MaxInt8)) ||
+			(rvk == reflect.Int16 && (num < math.MinInt16 || num > math.MaxInt16)) ||
+			(rvk == reflect.Int32 && (num < math.MinInt32 || num > math.MaxInt32)) {
+			return md.parseErr(errParseRange{i: num, size: rvk.String()})
+		}
+		rv.SetInt(num)
+	case rvk >= reflect.Uint && rvk <= reflect.Uint64:
+		unum := uint64(num)
+		if rvk == reflect.Uint8 && (num < 0 || unum > math.MaxUint8) ||
+			rvk == reflect.Uint16 && (num < 0 || unum > math.MaxUint16) ||
+			rvk == reflect.Uint32 && (num < 0 || unum > math.MaxUint32) {
+			return md.parseErr(errParseRange{i: num, size: rvk.String()})
+		}
+		rv.SetUint(unum)
+	default:
+		panic("unreachable")
+	}
+	return nil
 }
 
 func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error {
@@ -431,7 +486,7 @@ func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error {
 		rv.SetBool(b)
 		return nil
 	}
-	return badtype("boolean", data)
+	return md.badtype("boolean", data)
 }
 
 func (md *MetaData) unifyAnything(data interface{}, rv reflect.Value) error {
@@ -439,10 +494,16 @@ func (md *MetaData) unifyAnything(data interface{}, rv reflect.Value) error {
 	return nil
 }
 
-func (md *MetaData) unifyText(data interface{}, v TextUnmarshaler) error {
+func (md *MetaData) unifyText(data interface{}, v encoding.TextUnmarshaler) error {
 	var s string
 	switch sdata := data.(type) {
-	case TextMarshaler:
+	case Marshaler:
+		text, err := sdata.MarshalTOML()
+		if err != nil {
+			return err
+		}
+		s = string(text)
+	case encoding.TextMarshaler:
 		text, err := sdata.MarshalText()
 		if err != nil {
 			return err
@@ -459,7 +520,7 @@ func (md *MetaData) unifyText(data interface{}, v TextUnmarshaler) error {
 	case float64:
 		s = fmt.Sprintf("%f", sdata)
 	default:
-		return badtype("primitive (string-like)", data)
+		return md.badtype("primitive (string-like)", data)
 	}
 	if err := v.UnmarshalText([]byte(s)); err != nil {
 		return err
@@ -467,22 +528,54 @@ func (md *MetaData) unifyText(data interface{}, v TextUnmarshaler) error {
 	return nil
 }
 
+func (md *MetaData) badtype(dst string, data interface{}) error {
+	return md.e("incompatible types: TOML value has type %T; destination has type %s", data, dst)
+}
+
+func (md *MetaData) parseErr(err error) error {
+	k := md.context.String()
+	return ParseError{
+		LastKey:  k,
+		Position: md.keyInfo[k].pos,
+		Line:     md.keyInfo[k].pos.Line,
+		err:      err,
+		input:    string(md.data),
+	}
+}
+
+func (md *MetaData) e(format string, args ...interface{}) error {
+	f := "toml: "
+	if len(md.context) > 0 {
+		f = fmt.Sprintf("toml: (last key %q): ", md.context)
+		p := md.keyInfo[md.context.String()].pos
+		if p.Line > 0 {
+			f = fmt.Sprintf("toml: line %d (last key %q): ", p.Line, md.context)
+		}
+	}
+	return fmt.Errorf(f+format, args...)
+}
+
 // rvalue returns a reflect.Value of `v`. All pointers are resolved.
 func rvalue(v interface{}) reflect.Value {
 	return indirect(reflect.ValueOf(v))
 }
 
 // indirect returns the value pointed to by a pointer.
-// Pointers are followed until the value is not a pointer.
-// New values are allocated for each nil pointer.
 //
-// An exception to this rule is if the value satisfies an interface of
-// interest to us (like encoding.TextUnmarshaler).
+// Pointers are followed until the value is not a pointer. New values are
+// allocated for each nil pointer.
+//
+// An exception to this rule is if the value satisfies an interface of interest
+// to us (like encoding.TextUnmarshaler).
 func indirect(v reflect.Value) reflect.Value {
 	if v.Kind() != reflect.Ptr {
 		if v.CanSet() {
 			pv := v.Addr()
-			if _, ok := pv.Interface().(TextUnmarshaler); ok {
+			pvi := pv.Interface()
+			if _, ok := pvi.(encoding.TextUnmarshaler); ok {
+				return pv
+			}
+			if _, ok := pvi.(Unmarshaler); ok {
 				return pv
 			}
 		}
@@ -498,12 +591,12 @@ func isUnifiable(rv reflect.Value) bool {
 	if rv.CanSet() {
 		return true
 	}
-	if _, ok := rv.Interface().(TextUnmarshaler); ok {
+	rvi := rv.Interface()
+	if _, ok := rvi.(encoding.TextUnmarshaler); ok {
+		return true
+	}
+	if _, ok := rvi.(Unmarshaler); ok {
 		return true
 	}
 	return false
 }
-
-func badtype(expected string, data interface{}) error {
-	return e("cannot load TOML value of type %T into a Go %s", data, expected)
-}

+ 19 - 0
vendor/github.com/BurntSushi/toml/decode_go116.go

@@ -0,0 +1,19 @@
+//go:build go1.16
+// +build go1.16
+
+package toml
+
+import (
+	"io/fs"
+)
+
+// DecodeFS reads the contents of a file from [fs.FS] and decodes it with
+// [Decode].
+func DecodeFS(fsys fs.FS, path string, v interface{}) (MetaData, error) {
+	fp, err := fsys.Open(path)
+	if err != nil {
+		return MetaData{}, err
+	}
+	defer fp.Close()
+	return NewDecoder(fp).Decode(v)
+}

+ 0 - 121
vendor/github.com/BurntSushi/toml/decode_meta.go

@@ -1,121 +0,0 @@
-package toml
-
-import "strings"
-
-// MetaData allows access to meta information about TOML data that may not
-// be inferrable via reflection. In particular, whether a key has been defined
-// and the TOML type of a key.
-type MetaData struct {
-	mapping map[string]interface{}
-	types   map[string]tomlType
-	keys    []Key
-	decoded map[string]bool
-	context Key // Used only during decoding.
-}
-
-// IsDefined returns true if the key given exists in the TOML data. The key
-// should be specified hierarchially. e.g.,
-//
-//	// access the TOML key 'a.b.c'
-//	IsDefined("a", "b", "c")
-//
-// IsDefined will return false if an empty key given. Keys are case sensitive.
-func (md *MetaData) IsDefined(key ...string) bool {
-	if len(key) == 0 {
-		return false
-	}
-
-	var hash map[string]interface{}
-	var ok bool
-	var hashOrVal interface{} = md.mapping
-	for _, k := range key {
-		if hash, ok = hashOrVal.(map[string]interface{}); !ok {
-			return false
-		}
-		if hashOrVal, ok = hash[k]; !ok {
-			return false
-		}
-	}
-	return true
-}
-
-// Type returns a string representation of the type of the key specified.
-//
-// Type will return the empty string if given an empty key or a key that
-// does not exist. Keys are case sensitive.
-func (md *MetaData) Type(key ...string) string {
-	fullkey := strings.Join(key, ".")
-	if typ, ok := md.types[fullkey]; ok {
-		return typ.typeString()
-	}
-	return ""
-}
-
-// Key is the type of any TOML key, including key groups. Use (MetaData).Keys
-// to get values of this type.
-type Key []string
-
-func (k Key) String() string {
-	return strings.Join(k, ".")
-}
-
-func (k Key) maybeQuotedAll() string {
-	var ss []string
-	for i := range k {
-		ss = append(ss, k.maybeQuoted(i))
-	}
-	return strings.Join(ss, ".")
-}
-
-func (k Key) maybeQuoted(i int) string {
-	quote := false
-	for _, c := range k[i] {
-		if !isBareKeyChar(c) {
-			quote = true
-			break
-		}
-	}
-	if quote {
-		return "\"" + strings.Replace(k[i], "\"", "\\\"", -1) + "\""
-	}
-	return k[i]
-}
-
-func (k Key) add(piece string) Key {
-	newKey := make(Key, len(k)+1)
-	copy(newKey, k)
-	newKey[len(k)] = piece
-	return newKey
-}
-
-// Keys returns a slice of every key in the TOML data, including key groups.
-// Each key is itself a slice, where the first element is the top of the
-// hierarchy and the last is the most specific.
-//
-// The list will have the same order as the keys appeared in the TOML data.
-//
-// All keys returned are non-empty.
-func (md *MetaData) Keys() []Key {
-	return md.keys
-}
-
-// Undecoded returns all keys that have not been decoded in the order in which
-// they appear in the original TOML document.
-//
-// This includes keys that haven't been decoded because of a Primitive value.
-// Once the Primitive value is decoded, the keys will be considered decoded.
-//
-// Also note that decoding into an empty interface will result in no decoding,
-// and so no keys will be considered decoded.
-//
-// In this sense, the Undecoded keys correspond to keys in the TOML document
-// that do not have a concrete type in your representation.
-func (md *MetaData) Undecoded() []Key {
-	undecoded := make([]Key, 0, len(md.keys))
-	for _, key := range md.keys {
-		if !md.decoded[key.String()] {
-			undecoded = append(undecoded, key)
-		}
-	}
-	return undecoded
-}

+ 29 - 0
vendor/github.com/BurntSushi/toml/deprecated.go

@@ -0,0 +1,29 @@
+package toml
+
+import (
+	"encoding"
+	"io"
+)
+
+// TextMarshaler is an alias for encoding.TextMarshaler.
+//
+// Deprecated: use encoding.TextMarshaler
+type TextMarshaler encoding.TextMarshaler
+
+// TextUnmarshaler is an alias for encoding.TextUnmarshaler.
+//
+// Deprecated: use encoding.TextUnmarshaler
+type TextUnmarshaler encoding.TextUnmarshaler
+
+// PrimitiveDecode is an alias for MetaData.PrimitiveDecode().
+//
+// Deprecated: use MetaData.PrimitiveDecode.
+func PrimitiveDecode(primValue Primitive, v interface{}) error {
+	md := MetaData{decoded: make(map[string]struct{})}
+	return md.unify(primValue.undecoded, rvalue(v))
+}
+
+// DecodeReader is an alias for NewDecoder(r).Decode(v).
+//
+// Deprecated: use NewDecoder(reader).Decode(&value).
+func DecodeReader(r io.Reader, v interface{}) (MetaData, error) { return NewDecoder(r).Decode(v) }

+ 10 - 26
vendor/github.com/BurntSushi/toml/doc.go

@@ -1,27 +1,11 @@
-/*
-Package toml provides facilities for decoding and encoding TOML configuration
-files via reflection. There is also support for delaying decoding with
-the Primitive type, and querying the set of keys in a TOML document with the
-MetaData type.
-
-The specification implemented: https://github.com/toml-lang/toml
-
-The sub-command github.com/BurntSushi/toml/cmd/tomlv can be used to verify
-whether a file is a valid TOML document. It can also be used to print the
-type of each key in a TOML document.
-
-Testing
-
-There are two important types of tests used for this package. The first is
-contained inside '*_test.go' files and uses the standard Go unit testing
-framework. These tests are primarily devoted to holistically testing the
-decoder and encoder.
-
-The second type of testing is used to verify the implementation's adherence
-to the TOML specification. These tests have been factored into their own
-project: https://github.com/BurntSushi/toml-test
-
-The reason the tests are in a separate project is so that they can be used by
-any implementation of TOML. Namely, it is language agnostic.
-*/
+// Package toml implements decoding and encoding of TOML files.
+//
+// This package supports TOML v1.0.0, as specified at https://toml.io
+//
+// There is also support for delaying decoding with the Primitive type, and
+// querying the set of keys in a TOML document with the MetaData type.
+//
+// The github.com/BurntSushi/toml/cmd/tomlv package implements a TOML validator,
+// and can be used to verify if TOML document is valid. It can also be used to
+// print the type of each key.
 package toml

+ 406 - 215
vendor/github.com/BurntSushi/toml/encode.go

@@ -2,57 +2,127 @@ package toml
 
 import (
 	"bufio"
+	"encoding"
+	"encoding/json"
 	"errors"
 	"fmt"
 	"io"
+	"math"
 	"reflect"
 	"sort"
 	"strconv"
 	"strings"
 	"time"
+
+	"github.com/BurntSushi/toml/internal"
 )
 
 type tomlEncodeError struct{ error }
 
 var (
-	errArrayMixedElementTypes = errors.New(
-		"toml: cannot encode array with mixed element types")
-	errArrayNilElement = errors.New(
-		"toml: cannot encode array with nil element")
-	errNonString = errors.New(
-		"toml: cannot encode a map with non-string key type")
-	errAnonNonStruct = errors.New(
-		"toml: cannot encode an anonymous field that is not a struct")
-	errArrayNoTable = errors.New(
-		"toml: TOML array element cannot contain a table")
-	errNoKey = errors.New(
-		"toml: top-level values must be Go maps or structs")
-	errAnything = errors.New("") // used in testing
+	errArrayNilElement = errors.New("toml: cannot encode array with nil element")
+	errNonString       = errors.New("toml: cannot encode a map with non-string key type")
+	errNoKey           = errors.New("toml: top-level values must be Go maps or structs")
+	errAnything        = errors.New("") // used in testing
 )
 
-var quotedReplacer = strings.NewReplacer(
-	"\t", "\\t",
-	"\n", "\\n",
-	"\r", "\\r",
+var dblQuotedReplacer = strings.NewReplacer(
 	"\"", "\\\"",
 	"\\", "\\\\",
+	"\x00", `\u0000`,
+	"\x01", `\u0001`,
+	"\x02", `\u0002`,
+	"\x03", `\u0003`,
+	"\x04", `\u0004`,
+	"\x05", `\u0005`,
+	"\x06", `\u0006`,
+	"\x07", `\u0007`,
+	"\b", `\b`,
+	"\t", `\t`,
+	"\n", `\n`,
+	"\x0b", `\u000b`,
+	"\f", `\f`,
+	"\r", `\r`,
+	"\x0e", `\u000e`,
+	"\x0f", `\u000f`,
+	"\x10", `\u0010`,
+	"\x11", `\u0011`,
+	"\x12", `\u0012`,
+	"\x13", `\u0013`,
+	"\x14", `\u0014`,
+	"\x15", `\u0015`,
+	"\x16", `\u0016`,
+	"\x17", `\u0017`,
+	"\x18", `\u0018`,
+	"\x19", `\u0019`,
+	"\x1a", `\u001a`,
+	"\x1b", `\u001b`,
+	"\x1c", `\u001c`,
+	"\x1d", `\u001d`,
+	"\x1e", `\u001e`,
+	"\x1f", `\u001f`,
+	"\x7f", `\u007f`,
 )
 
-// Encoder controls the encoding of Go values to a TOML document to some
-// io.Writer.
+var (
+	marshalToml = reflect.TypeOf((*Marshaler)(nil)).Elem()
+	marshalText = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
+	timeType    = reflect.TypeOf((*time.Time)(nil)).Elem()
+)
+
+// Marshaler is the interface implemented by types that can marshal themselves
+// into valid TOML.
+type Marshaler interface {
+	MarshalTOML() ([]byte, error)
+}
+
+// Encoder encodes a Go to a TOML document.
+//
+// The mapping between Go values and TOML values should be precisely the same as
+// for [Decode].
+//
+// time.Time is encoded as a RFC 3339 string, and time.Duration as its string
+// representation.
+//
+// The [Marshaler] and [encoding.TextMarshaler] interfaces are supported to
+// encoding the value as custom TOML.
 //
-// The indentation level can be controlled with the Indent field.
+// If you want to write arbitrary binary data then you will need to use
+// something like base64 since TOML does not have any binary types.
+//
+// When encoding TOML hashes (Go maps or structs), keys without any sub-hashes
+// are encoded first.
+//
+// Go maps will be sorted alphabetically by key for deterministic output.
+//
+// The toml struct tag can be used to provide the key name; if omitted the
+// struct field name will be used. If the "omitempty" option is present the
+// following value will be skipped:
+//
+//   - arrays, slices, maps, and string with len of 0
+//   - struct with all zero values
+//   - bool false
+//
+// If omitzero is given all int and float types with a value of 0 will be
+// skipped.
+//
+// Encoding Go values without a corresponding TOML representation will return an
+// error. Examples of this includes maps with non-string keys, slices with nil
+// elements, embedded non-struct types, and nested slices containing maps or
+// structs. (e.g. [][]map[string]string is not allowed but []map[string]string
+// is okay, as is []map[string][]string).
+//
+// NOTE: only exported keys are encoded due to the use of reflection. Unexported
+// keys are silently discarded.
 type Encoder struct {
-	// A single indentation level. By default it is two spaces.
+	// String to use for a single indentation level; default is two spaces.
 	Indent string
 
-	// hasWritten is whether we have written any output to w yet.
-	hasWritten bool
 	w          *bufio.Writer
+	hasWritten bool // written any output to w yet?
 }
 
-// NewEncoder returns a TOML encoder that encodes Go values to the io.Writer
-// given. By default, a single indentation level is 2 spaces.
+// NewEncoder create a new Encoder.
 func NewEncoder(w io.Writer) *Encoder {
 	return &Encoder{
 		w:      bufio.NewWriter(w),
@@ -60,32 +130,14 @@ func NewEncoder(w io.Writer) *Encoder {
 	}
 }
 
-// Encode writes a TOML representation of the Go value to the underlying
-// io.Writer. If the value given cannot be encoded to a valid TOML document,
-// then an error is returned.
-//
-// The mapping between Go values and TOML values should be precisely the same
-// as for the Decode* functions. Similarly, the TextMarshaler interface is
-// supported by encoding the resulting bytes as strings. (If you want to write
-// arbitrary binary data then you will need to use something like base64 since
-// TOML does not have any binary types.)
-//
-// When encoding TOML hashes (i.e., Go maps or structs), keys without any
-// sub-hashes are encoded first.
+// Encode writes a TOML representation of the Go value to the [Encoder]'s writer.
 //
-// If a Go map is encoded, then its keys are sorted alphabetically for
-// deterministic output. More control over this behavior may be provided if
-// there is demand for it.
-//
-// Encoding Go values without a corresponding TOML representation---like map
-// types with non-string keys---will cause an error to be returned. Similarly
-// for mixed arrays/slices, arrays/slices with nil elements, embedded
-// non-struct types and nested slices containing maps or structs.
-// (e.g., [][]map[string]string is not allowed but []map[string]string is OK
-// and so is []map[string][]string.)
+// An error is returned if the value given cannot be encoded to a valid TOML
+// document.
 func (enc *Encoder) Encode(v interface{}) error {
 	rv := eindirect(reflect.ValueOf(v))
-	if err := enc.safeEncode(Key([]string{}), rv); err != nil {
+	err := enc.safeEncode(Key([]string{}), rv)
+	if err != nil {
 		return err
 	}
 	return enc.w.Flush()
@@ -106,13 +158,15 @@ func (enc *Encoder) safeEncode(key Key, rv reflect.Value) (err error) {
 }
 
 func (enc *Encoder) encode(key Key, rv reflect.Value) {
-	// Special case. Time needs to be in ISO8601 format.
-	// Special case. If we can marshal the type to text, then we used that.
-	// Basically, this prevents the encoder for handling these types as
-	// generic structs (or whatever the underlying type of a TextMarshaler is).
-	switch rv.Interface().(type) {
-	case time.Time, TextMarshaler:
-		enc.keyEqElement(key, rv)
+	// If we can marshal the type to text, then we use that. This prevents the
+	// encoder for handling these types as generic structs (or whatever the
+	// underlying type of a TextMarshaler is).
+	switch {
+	case isMarshaler(rv):
+		enc.writeKeyValue(key, rv, false)
+		return
+	case rv.Type() == primitiveType: // TODO: #76 would make this superfluous after implemented.
+		enc.encode(key, reflect.ValueOf(rv.Interface().(Primitive).undecoded))
 		return
 	}
 
@@ -123,12 +177,12 @@ func (enc *Encoder) encode(key Key, rv reflect.Value) {
 		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
 		reflect.Uint64,
 		reflect.Float32, reflect.Float64, reflect.String, reflect.Bool:
-		enc.keyEqElement(key, rv)
+		enc.writeKeyValue(key, rv, false)
 	case reflect.Array, reflect.Slice:
 		if typeEqual(tomlArrayHash, tomlTypeOfGo(rv)) {
 			enc.eArrayOfTables(key, rv)
 		} else {
-			enc.keyEqElement(key, rv)
+			enc.writeKeyValue(key, rv, false)
 		}
 	case reflect.Interface:
 		if rv.IsNil() {
@@ -148,55 +202,114 @@ func (enc *Encoder) encode(key Key, rv reflect.Value) {
 	case reflect.Struct:
 		enc.eTable(key, rv)
 	default:
-		panic(e("unsupported type for key '%s': %s", key, k))
+		encPanic(fmt.Errorf("unsupported type for key '%s': %s", key, k))
 	}
 }
 
-// eElement encodes any value that can be an array element (primitives and
-// arrays).
+// eElement encodes any value that can be an array element.
 func (enc *Encoder) eElement(rv reflect.Value) {
 	switch v := rv.Interface().(type) {
-	case time.Time:
-		// Special case time.Time as a primitive. Has to come before
-		// TextMarshaler below because time.Time implements
-		// encoding.TextMarshaler, but we need to always use UTC.
-		enc.wf(v.UTC().Format("2006-01-02T15:04:05Z"))
+	case time.Time: // Using TextMarshaler adds extra quotes, which we don't want.
+		format := time.RFC3339Nano
+		switch v.Location() {
+		case internal.LocalDatetime:
+			format = "2006-01-02T15:04:05.999999999"
+		case internal.LocalDate:
+			format = "2006-01-02"
+		case internal.LocalTime:
+			format = "15:04:05.999999999"
+		}
+		switch v.Location() {
+		default:
+			enc.wf(v.Format(format))
+		case internal.LocalDatetime, internal.LocalDate, internal.LocalTime:
+			enc.wf(v.In(time.UTC).Format(format))
+		}
 		return
-	case TextMarshaler:
-		// Special case. Use text marshaler if it's available for this value.
-		if s, err := v.MarshalText(); err != nil {
+	case Marshaler:
+		s, err := v.MarshalTOML()
+		if err != nil {
 			encPanic(err)
-		} else {
-			enc.writeQuoted(string(s))
 		}
+		if s == nil {
+			encPanic(errors.New("MarshalTOML returned nil and no error"))
+		}
+		enc.w.Write(s)
+		return
+	case encoding.TextMarshaler:
+		s, err := v.MarshalText()
+		if err != nil {
+			encPanic(err)
+		}
+		if s == nil {
+			encPanic(errors.New("MarshalText returned nil and no error"))
+		}
+		enc.writeQuoted(string(s))
+		return
+	case time.Duration:
+		enc.writeQuoted(v.String())
 		return
+	case json.Number:
+		n, _ := rv.Interface().(json.Number)
+
+		if n == "" { /// Useful zero value.
+			enc.w.WriteByte('0')
+			return
+		} else if v, err := n.Int64(); err == nil {
+			enc.eElement(reflect.ValueOf(v))
+			return
+		} else if v, err := n.Float64(); err == nil {
+			enc.eElement(reflect.ValueOf(v))
+			return
+		}
+		encPanic(fmt.Errorf("unable to convert %q to int64 or float64", n))
 	}
+
 	switch rv.Kind() {
+	case reflect.Ptr:
+		enc.eElement(rv.Elem())
+		return
+	case reflect.String:
+		enc.writeQuoted(rv.String())
 	case reflect.Bool:
 		enc.wf(strconv.FormatBool(rv.Bool()))
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
-		reflect.Int64:
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 		enc.wf(strconv.FormatInt(rv.Int(), 10))
-	case reflect.Uint, reflect.Uint8, reflect.Uint16,
-		reflect.Uint32, reflect.Uint64:
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
 		enc.wf(strconv.FormatUint(rv.Uint(), 10))
 	case reflect.Float32:
-		enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 32)))
+		f := rv.Float()
+		if math.IsNaN(f) {
+			enc.wf("nan")
+		} else if math.IsInf(f, 0) {
+			enc.wf("%cinf", map[bool]byte{true: '-', false: '+'}[math.Signbit(f)])
+		} else {
+			enc.wf(floatAddDecimal(strconv.FormatFloat(f, 'f', -1, 32)))
+		}
 	case reflect.Float64:
-		enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 64)))
+		f := rv.Float()
+		if math.IsNaN(f) {
+			enc.wf("nan")
+		} else if math.IsInf(f, 0) {
+			enc.wf("%cinf", map[bool]byte{true: '-', false: '+'}[math.Signbit(f)])
+		} else {
+			enc.wf(floatAddDecimal(strconv.FormatFloat(f, 'f', -1, 64)))
+		}
 	case reflect.Array, reflect.Slice:
 		enc.eArrayOrSliceElement(rv)
+	case reflect.Struct:
+		enc.eStruct(nil, rv, true)
+	case reflect.Map:
+		enc.eMap(nil, rv, true)
 	case reflect.Interface:
 		enc.eElement(rv.Elem())
-	case reflect.String:
-		enc.writeQuoted(rv.String())
 	default:
-		panic(e("unexpected primitive type: %s", rv.Kind()))
+		encPanic(fmt.Errorf("unexpected type: %T", rv.Interface()))
 	}
 }
 
-// By the TOML spec, all floats must have a decimal with at least one
-// number on either side.
+// By the TOML spec, all floats must have a decimal with at least one number on
+// either side.
 func floatAddDecimal(fstr string) string {
 	if !strings.Contains(fstr, ".") {
 		return fstr + ".0"
@@ -205,14 +318,14 @@ func floatAddDecimal(fstr string) string {
 }
 
 func (enc *Encoder) writeQuoted(s string) {
-	enc.wf("\"%s\"", quotedReplacer.Replace(s))
+	enc.wf("\"%s\"", dblQuotedReplacer.Replace(s))
 }
 
 func (enc *Encoder) eArrayOrSliceElement(rv reflect.Value) {
 	length := rv.Len()
 	enc.wf("[")
 	for i := 0; i < length; i++ {
-		elem := rv.Index(i)
+		elem := eindirect(rv.Index(i))
 		enc.eElement(elem)
 		if i != length-1 {
 			enc.wf(", ")
@@ -226,44 +339,43 @@ func (enc *Encoder) eArrayOfTables(key Key, rv reflect.Value) {
 		encPanic(errNoKey)
 	}
 	for i := 0; i < rv.Len(); i++ {
-		trv := rv.Index(i)
+		trv := eindirect(rv.Index(i))
 		if isNil(trv) {
 			continue
 		}
-		panicIfInvalidKey(key)
 		enc.newline()
-		enc.wf("%s[[%s]]", enc.indentStr(key), key.maybeQuotedAll())
+		enc.wf("%s[[%s]]", enc.indentStr(key), key)
 		enc.newline()
-		enc.eMapOrStruct(key, trv)
+		enc.eMapOrStruct(key, trv, false)
 	}
 }
 
 func (enc *Encoder) eTable(key Key, rv reflect.Value) {
-	panicIfInvalidKey(key)
 	if len(key) == 1 {
 		// Output an extra newline between top-level tables.
 		// (The newline isn't written if nothing else has been written though.)
 		enc.newline()
 	}
 	if len(key) > 0 {
-		enc.wf("%s[%s]", enc.indentStr(key), key.maybeQuotedAll())
+		enc.wf("%s[%s]", enc.indentStr(key), key)
 		enc.newline()
 	}
-	enc.eMapOrStruct(key, rv)
+	enc.eMapOrStruct(key, rv, false)
 }
 
-func (enc *Encoder) eMapOrStruct(key Key, rv reflect.Value) {
-	switch rv := eindirect(rv); rv.Kind() {
+func (enc *Encoder) eMapOrStruct(key Key, rv reflect.Value, inline bool) {
+	switch rv.Kind() {
 	case reflect.Map:
-		enc.eMap(key, rv)
+		enc.eMap(key, rv, inline)
 	case reflect.Struct:
-		enc.eStruct(key, rv)
+		enc.eStruct(key, rv, inline)
 	default:
+		// Should never happen?
 		panic("eTable: unhandled reflect.Value Kind: " + rv.Kind().String())
 	}
 }
 
-func (enc *Encoder) eMap(key Key, rv reflect.Value) {
+func (enc *Encoder) eMap(key Key, rv reflect.Value, inline bool) {
 	rt := rv.Type()
 	if rt.Key().Kind() != reflect.String {
 		encPanic(errNonString)
@@ -274,68 +386,100 @@ func (enc *Encoder) eMap(key Key, rv reflect.Value) {
 	var mapKeysDirect, mapKeysSub []string
 	for _, mapKey := range rv.MapKeys() {
 		k := mapKey.String()
-		if typeIsHash(tomlTypeOfGo(rv.MapIndex(mapKey))) {
+		if typeIsTable(tomlTypeOfGo(eindirect(rv.MapIndex(mapKey)))) {
 			mapKeysSub = append(mapKeysSub, k)
 		} else {
 			mapKeysDirect = append(mapKeysDirect, k)
 		}
 	}
 
-	var writeMapKeys = func(mapKeys []string) {
+	var writeMapKeys = func(mapKeys []string, trailC bool) {
 		sort.Strings(mapKeys)
-		for _, mapKey := range mapKeys {
-			mrv := rv.MapIndex(reflect.ValueOf(mapKey))
-			if isNil(mrv) {
-				// Don't write anything for nil fields.
+		for i, mapKey := range mapKeys {
+			val := eindirect(rv.MapIndex(reflect.ValueOf(mapKey)))
+			if isNil(val) {
 				continue
 			}
-			enc.encode(key.add(mapKey), mrv)
+
+			if inline {
+				enc.writeKeyValue(Key{mapKey}, val, true)
+				if trailC || i != len(mapKeys)-1 {
+					enc.wf(", ")
+				}
+			} else {
+				enc.encode(key.add(mapKey), val)
+			}
 		}
 	}
-	writeMapKeys(mapKeysDirect)
-	writeMapKeys(mapKeysSub)
+
+	if inline {
+		enc.wf("{")
+	}
+	writeMapKeys(mapKeysDirect, len(mapKeysSub) > 0)
+	writeMapKeys(mapKeysSub, false)
+	if inline {
+		enc.wf("}")
+	}
 }
 
-func (enc *Encoder) eStruct(key Key, rv reflect.Value) {
+const is32Bit = (32 << (^uint(0) >> 63)) == 32
+
+func pointerTo(t reflect.Type) reflect.Type {
+	if t.Kind() == reflect.Ptr {
+		return pointerTo(t.Elem())
+	}
+	return t
+}
+
+func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
 	// Write keys for fields directly under this key first, because if we write
-	// a field that creates a new table, then all keys under it will be in that
+	// a field that creates a new table then all keys under it will be in that
 	// table (not the one we're writing here).
-	rt := rv.Type()
-	var fieldsDirect, fieldsSub [][]int
-	var addFields func(rt reflect.Type, rv reflect.Value, start []int)
+	//
+	// Fields is a [][]int: for fieldsDirect this always has one entry (the
+	// struct index). For fieldsSub it contains two entries: the parent field
+	// index from tv, and the field indexes for the fields of the sub.
+	var (
+		rt                      = rv.Type()
+		fieldsDirect, fieldsSub [][]int
+		addFields               func(rt reflect.Type, rv reflect.Value, start []int)
+	)
 	addFields = func(rt reflect.Type, rv reflect.Value, start []int) {
 		for i := 0; i < rt.NumField(); i++ {
 			f := rt.Field(i)
-			// skip unexported fields
-			if f.PkgPath != "" && !f.Anonymous {
+			isEmbed := f.Anonymous && pointerTo(f.Type).Kind() == reflect.Struct
+			if f.PkgPath != "" && !isEmbed { /// Skip unexported fields.
+				continue
+			}
+			opts := getOptions(f.Tag)
+			if opts.skip {
 				continue
 			}
-			frv := rv.Field(i)
-			if f.Anonymous {
-				t := f.Type
-				switch t.Kind() {
-				case reflect.Struct:
-					// Treat anonymous struct fields with
-					// tag names as though they are not
-					// anonymous, like encoding/json does.
-					if getOptions(f.Tag).name == "" {
-						addFields(t, frv, f.Index)
-						continue
-					}
-				case reflect.Ptr:
-					if t.Elem().Kind() == reflect.Struct &&
-						getOptions(f.Tag).name == "" {
-						if !frv.IsNil() {
-							addFields(t.Elem(), frv.Elem(), f.Index)
-						}
-						continue
-					}
-					// Fall through to the normal field encoding logic below
-					// for non-struct anonymous fields.
+
+			frv := eindirect(rv.Field(i))
+
+			if is32Bit {
+				// Copy so it works correct on 32bit archs; not clear why this
+				// is needed. See #314, and https://www.reddit.com/r/golang/comments/pnx8v4
+				// This also works fine on 64bit, but 32bit archs are somewhat
+				// rare and this is a wee bit faster.
+				copyStart := make([]int, len(start))
+				copy(copyStart, start)
+				start = copyStart
+			}
+
+			// Treat anonymous struct fields with tag names as though they are
+			// not anonymous, like encoding/json does.
+			//
+			// Non-struct anonymous fields use the normal encoding logic.
+			if isEmbed {
+				if getOptions(f.Tag).name == "" && frv.Kind() == reflect.Struct {
+					addFields(frv.Type(), frv, append(start, f.Index...))
+					continue
 				}
 			}
 
-			if typeIsHash(tomlTypeOfGo(frv)) {
+			if typeIsTable(tomlTypeOfGo(frv)) {
 				fieldsSub = append(fieldsSub, append(start, f.Index...))
 			} else {
 				fieldsDirect = append(fieldsDirect, append(start, f.Index...))
@@ -344,48 +488,81 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value) {
 	}
 	addFields(rt, rv, nil)
 
-	var writeFields = func(fields [][]int) {
+	writeFields := func(fields [][]int) {
 		for _, fieldIndex := range fields {
-			sft := rt.FieldByIndex(fieldIndex)
-			sf := rv.FieldByIndex(fieldIndex)
-			if isNil(sf) {
-				// Don't write anything for nil fields.
+			fieldType := rt.FieldByIndex(fieldIndex)
+			fieldVal := rv.FieldByIndex(fieldIndex)
+
+			opts := getOptions(fieldType.Tag)
+			if opts.skip {
+				continue
+			}
+			if opts.omitempty && isEmpty(fieldVal) {
 				continue
 			}
 
-			opts := getOptions(sft.Tag)
-			if opts.skip {
+			fieldVal = eindirect(fieldVal)
+
+			if isNil(fieldVal) { /// Don't write anything for nil fields.
 				continue
 			}
-			keyName := sft.Name
+
+			keyName := fieldType.Name
 			if opts.name != "" {
 				keyName = opts.name
 			}
-			if opts.omitempty && isEmpty(sf) {
-				continue
-			}
-			if opts.omitzero && isZero(sf) {
+
+			if opts.omitzero && isZero(fieldVal) {
 				continue
 			}
 
-			enc.encode(key.add(keyName), sf)
+			if inline {
+				enc.writeKeyValue(Key{keyName}, fieldVal, true)
+				if fieldIndex[0] != len(fields)-1 {
+					enc.wf(", ")
+				}
+			} else {
+				enc.encode(key.add(keyName), fieldVal)
+			}
 		}
 	}
+
+	if inline {
+		enc.wf("{")
+	}
 	writeFields(fieldsDirect)
 	writeFields(fieldsSub)
+	if inline {
+		enc.wf("}")
+	}
 }
 
-// tomlTypeName returns the TOML type name of the Go value's type. It is
-// used to determine whether the types of array elements are mixed (which is
-// forbidden). If the Go value is nil, then it is illegal for it to be an array
-// element, and valueIsNil is returned as true.
-
-// Returns the TOML type of a Go value. The type may be `nil`, which means
-// no concrete TOML type could be found.
+// tomlTypeOfGo returns the TOML type name of the Go value's type.
+//
+// It is used to determine whether the types of array elements are mixed (which
+// is forbidden). If the Go value is nil, then it is illegal for it to be an
+// array element, and valueIsNil is returned as true.
+//
+// The type may be `nil`, which means no concrete TOML type could be found.
 func tomlTypeOfGo(rv reflect.Value) tomlType {
 	if isNil(rv) || !rv.IsValid() {
 		return nil
 	}
+
+	if rv.Kind() == reflect.Struct {
+		if rv.Type() == timeType {
+			return tomlDatetime
+		}
+		if isMarshaler(rv) {
+			return tomlString
+		}
+		return tomlHash
+	}
+
+	if isMarshaler(rv) {
+		return tomlString
+	}
+
 	switch rv.Kind() {
 	case reflect.Bool:
 		return tomlBool
@@ -397,7 +574,7 @@ func tomlTypeOfGo(rv reflect.Value) tomlType {
 	case reflect.Float32, reflect.Float64:
 		return tomlFloat
 	case reflect.Array, reflect.Slice:
-		if typeEqual(tomlHash, tomlArrayType(rv)) {
+		if isTableArray(rv) {
 			return tomlArrayHash
 		}
 		return tomlArray
@@ -407,54 +584,35 @@ func tomlTypeOfGo(rv reflect.Value) tomlType {
 		return tomlString
 	case reflect.Map:
 		return tomlHash
-	case reflect.Struct:
-		switch rv.Interface().(type) {
-		case time.Time:
-			return tomlDatetime
-		case TextMarshaler:
-			return tomlString
-		default:
-			return tomlHash
-		}
 	default:
-		panic("unexpected reflect.Kind: " + rv.Kind().String())
+		encPanic(errors.New("unsupported type: " + rv.Kind().String()))
+		panic("unreachable")
 	}
 }
 
-// tomlArrayType returns the element type of a TOML array. The type returned
-// may be nil if it cannot be determined (e.g., a nil slice or a zero length
-// slize). This function may also panic if it finds a type that cannot be
-// expressed in TOML (such as nil elements, heterogeneous arrays or directly
-// nested arrays of tables).
-func tomlArrayType(rv reflect.Value) tomlType {
-	if isNil(rv) || !rv.IsValid() || rv.Len() == 0 {
-		return nil
-	}
-	firstType := tomlTypeOfGo(rv.Index(0))
-	if firstType == nil {
-		encPanic(errArrayNilElement)
+func isMarshaler(rv reflect.Value) bool {
+	return rv.Type().Implements(marshalText) || rv.Type().Implements(marshalToml)
+}
+
+// isTableArray reports if all entries in the array or slice are a table.
+func isTableArray(arr reflect.Value) bool {
+	if isNil(arr) || !arr.IsValid() || arr.Len() == 0 {
+		return false
 	}
 
-	rvlen := rv.Len()
-	for i := 1; i < rvlen; i++ {
-		elem := rv.Index(i)
-		switch elemType := tomlTypeOfGo(elem); {
-		case elemType == nil:
+	ret := true
+	for i := 0; i < arr.Len(); i++ {
+		tt := tomlTypeOfGo(eindirect(arr.Index(i)))
+		// Don't allow nil.
+		if tt == nil {
 			encPanic(errArrayNilElement)
-		case !typeEqual(firstType, elemType):
-			encPanic(errArrayMixedElementTypes)
 		}
-	}
-	// If we have a nested array, then we must make sure that the nested
-	// array contains ONLY primitives.
-	// This checks arbitrarily nested arrays.
-	if typeEqual(firstType, tomlArray) || typeEqual(firstType, tomlArrayHash) {
-		nest := tomlArrayType(eindirect(rv.Index(0)))
-		if typeEqual(nest, tomlHash) || typeEqual(nest, tomlArrayHash) {
-			encPanic(errArrayNoTable)
+
+		if ret && !typeEqual(tomlHash, tt) {
+			ret = false
 		}
 	}
-	return firstType
+	return ret
 }
 
 type tagOptions struct {
@@ -499,8 +657,26 @@ func isEmpty(rv reflect.Value) bool {
 	switch rv.Kind() {
 	case reflect.Array, reflect.Slice, reflect.Map, reflect.String:
 		return rv.Len() == 0
+	case reflect.Struct:
+		if rv.Type().Comparable() {
+			return reflect.Zero(rv.Type()).Interface() == rv.Interface()
+		}
+		// Need to also check if all the fields are empty, otherwise something
+		// like this with uncomparable types will always return true:
+		//
+		//   type a struct{ field b }
+		//   type b struct{ s []string }
+		//   s := a{field: b{s: []string{"AAA"}}}
+		for i := 0; i < rv.NumField(); i++ {
+			if !isEmpty(rv.Field(i)) {
+				return false
+			}
+		}
+		return true
 	case reflect.Bool:
 		return !rv.Bool()
+	case reflect.Ptr:
+		return rv.IsNil()
 	}
 	return false
 }
@@ -511,18 +687,34 @@ func (enc *Encoder) newline() {
 	}
 }
 
-func (enc *Encoder) keyEqElement(key Key, val reflect.Value) {
+// Write a key/value pair:
+//
+//	key = <any value>
+//
+// This is also used for "k = v" in inline tables; so something like this will
+// be written in three calls:
+//
+//	┌───────────────────┐
+//	│      ┌───┐  ┌────┐│
+//	v      v   v  v    vv
+//	key = {k = 1, k2 = 2}
+func (enc *Encoder) writeKeyValue(key Key, val reflect.Value, inline bool) {
+	/// Marshaler used on top-level document; call eElement() to just call
+	/// Marshal{TOML,Text}.
 	if len(key) == 0 {
-		encPanic(errNoKey)
+		enc.eElement(val)
+		return
 	}
-	panicIfInvalidKey(key)
 	enc.wf("%s%s = ", enc.indentStr(key), key.maybeQuoted(len(key)-1))
 	enc.eElement(val)
-	enc.newline()
+	if !inline {
+		enc.newline()
+	}
 }
 
 func (enc *Encoder) wf(format string, v ...interface{}) {
-	if _, err := fmt.Fprintf(enc.w, format, v...); err != nil {
+	_, err := fmt.Fprintf(enc.w, format, v...)
+	if err != nil {
 		encPanic(err)
 	}
 	enc.hasWritten = true
@@ -536,13 +728,25 @@ func encPanic(err error) {
 	panic(tomlEncodeError{err})
 }
 
+// Resolve any level of pointers to the actual value (e.g. **string → string).
 func eindirect(v reflect.Value) reflect.Value {
-	switch v.Kind() {
-	case reflect.Ptr, reflect.Interface:
-		return eindirect(v.Elem())
-	default:
+	if v.Kind() != reflect.Ptr && v.Kind() != reflect.Interface {
+		if isMarshaler(v) {
+			return v
+		}
+		if v.CanAddr() { /// Special case for marshalers; see #358.
+			if pv := v.Addr(); isMarshaler(pv) {
+				return pv
+			}
+		}
 		return v
 	}
+
+	if v.IsNil() {
+		return v
+	}
+
+	return eindirect(v.Elem())
 }
 
 func isNil(rv reflect.Value) bool {
@@ -553,16 +757,3 @@ func isNil(rv reflect.Value) bool {
 		return false
 	}
 }
-
-func panicIfInvalidKey(key Key) {
-	for _, k := range key {
-		if len(k) == 0 {
-			encPanic(e("Key '%s' is not a valid table name. Key names "+
-				"cannot be empty.", key.maybeQuotedAll()))
-		}
-	}
-}
-
-func isValidKeyName(s string) bool {
-	return len(s) != 0
-}

+ 0 - 19
vendor/github.com/BurntSushi/toml/encoding_types.go

@@ -1,19 +0,0 @@
-// +build go1.2
-
-package toml
-
-// In order to support Go 1.1, we define our own TextMarshaler and
-// TextUnmarshaler types. For Go 1.2+, we just alias them with the
-// standard library interfaces.
-
-import (
-	"encoding"
-)
-
-// TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here
-// so that Go 1.1 can be supported.
-type TextMarshaler encoding.TextMarshaler
-
-// TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined
-// here so that Go 1.1 can be supported.
-type TextUnmarshaler encoding.TextUnmarshaler

+ 0 - 18
vendor/github.com/BurntSushi/toml/encoding_types_1.1.go

@@ -1,18 +0,0 @@
-// +build !go1.2
-
-package toml
-
-// These interfaces were introduced in Go 1.2, so we add them manually when
-// compiling for Go 1.1.
-
-// TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here
-// so that Go 1.1 can be supported.
-type TextMarshaler interface {
-	MarshalText() (text []byte, err error)
-}
-
-// TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined
-// here so that Go 1.1 can be supported.
-type TextUnmarshaler interface {
-	UnmarshalText(text []byte) error
-}

+ 279 - 0
vendor/github.com/BurntSushi/toml/error.go

@@ -0,0 +1,279 @@
+package toml
+
+import (
+	"fmt"
+	"strings"
+)
+
+// ParseError is returned when there is an error parsing the TOML syntax such as
+// invalid syntax, duplicate keys, etc.
+//
+// In addition to the error message itself, you can also print detailed location
+// information with context by using [ErrorWithPosition]:
+//
+//	toml: error: Key 'fruit' was already created and cannot be used as an array.
+//
+//	At line 4, column 2-7:
+//
+//	      2 | fruit = []
+//	      3 |
+//	      4 | [[fruit]] # Not allowed
+//	            ^^^^^
+//
+// [ErrorWithUsage] can be used to print the above with some more detailed usage
+// guidance:
+//
+//	toml: error: newlines not allowed within inline tables
+//
+//	At line 1, column 18:
+//
+//	      1 | x = [{ key = 42 #
+//	                           ^
+//
+//	Error help:
+//
+//	  Inline tables must always be on a single line:
+//
+//	      table = {key = 42, second = 43}
+//
+//	  It is invalid to split them over multiple lines like so:
+//
+//	      # INVALID
+//	      table = {
+//	          key    = 42,
+//	          second = 43
+//	      }
+//
+//	  Use regular for this:
+//
+//	      [table]
+//	      key    = 42
+//	      second = 43
+type ParseError struct {
+	Message  string   // Short technical message.
+	Usage    string   // Longer message with usage guidance; may be blank.
+	Position Position // Position of the error
+	LastKey  string   // Last parsed key, may be blank.
+
+	// Line the error occurred.
+	//
+	// Deprecated: use [Position].
+	Line int
+
+	err   error
+	input string
+}
+
+// Position of an error.
+type Position struct {
+	Line  int // Line number, starting at 1.
+	Start int // Start of error, as byte offset starting at 0.
+	Len   int // Lenght in bytes.
+}
+
+func (pe ParseError) Error() string {
+	msg := pe.Message
+	if msg == "" { // Error from errorf()
+		msg = pe.err.Error()
+	}
+
+	if pe.LastKey == "" {
+		return fmt.Sprintf("toml: line %d: %s", pe.Position.Line, msg)
+	}
+	return fmt.Sprintf("toml: line %d (last key %q): %s",
+		pe.Position.Line, pe.LastKey, msg)
+}
+
+// ErrorWithPosition returns the error with detailed location context.
+//
+// See the documentation on [ParseError].
+func (pe ParseError) ErrorWithPosition() string {
+	if pe.input == "" { // Should never happen, but just in case.
+		return pe.Error()
+	}
+
+	var (
+		lines = strings.Split(pe.input, "\n")
+		col   = pe.column(lines)
+		b     = new(strings.Builder)
+	)
+
+	msg := pe.Message
+	if msg == "" {
+		msg = pe.err.Error()
+	}
+
+	// TODO: don't show control characters as literals? This may not show up
+	// well everywhere.
+
+	if pe.Position.Len == 1 {
+		fmt.Fprintf(b, "toml: error: %s\n\nAt line %d, column %d:\n\n",
+			msg, pe.Position.Line, col+1)
+	} else {
+		fmt.Fprintf(b, "toml: error: %s\n\nAt line %d, column %d-%d:\n\n",
+			msg, pe.Position.Line, col, col+pe.Position.Len)
+	}
+	if pe.Position.Line > 2 {
+		fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-2, lines[pe.Position.Line-3])
+	}
+	if pe.Position.Line > 1 {
+		fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-1, lines[pe.Position.Line-2])
+	}
+	fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line, lines[pe.Position.Line-1])
+	fmt.Fprintf(b, "% 10s%s%s\n", "", strings.Repeat(" ", col), strings.Repeat("^", pe.Position.Len))
+	return b.String()
+}
+
+// ErrorWithUsage returns the error with detailed location context and usage
+// guidance.
+//
+// See the documentation on [ParseError].
+func (pe ParseError) ErrorWithUsage() string {
+	m := pe.ErrorWithPosition()
+	if u, ok := pe.err.(interface{ Usage() string }); ok && u.Usage() != "" {
+		lines := strings.Split(strings.TrimSpace(u.Usage()), "\n")
+		for i := range lines {
+			if lines[i] != "" {
+				lines[i] = "    " + lines[i]
+			}
+		}
+		return m + "Error help:\n\n" + strings.Join(lines, "\n") + "\n"
+	}
+	return m
+}
+
+func (pe ParseError) column(lines []string) int {
+	var pos, col int
+	for i := range lines {
+		ll := len(lines[i]) + 1 // +1 for the removed newline
+		if pos+ll >= pe.Position.Start {
+			col = pe.Position.Start - pos
+			if col < 0 { // Should never happen, but just in case.
+				col = 0
+			}
+			break
+		}
+		pos += ll
+	}
+
+	return col
+}
+
+type (
+	errLexControl       struct{ r rune }
+	errLexEscape        struct{ r rune }
+	errLexUTF8          struct{ b byte }
+	errLexInvalidNum    struct{ v string }
+	errLexInvalidDate   struct{ v string }
+	errLexInlineTableNL struct{}
+	errLexStringNL      struct{}
+	errParseRange       struct {
+		i    interface{} // int or float
+		size string      // "int64", "uint16", etc.
+	}
+	errParseDuration struct{ d string }
+)
+
+func (e errLexControl) Error() string {
+	return fmt.Sprintf("TOML files cannot contain control characters: '0x%02x'", e.r)
+}
+func (e errLexControl) Usage() string { return "" }
+
+func (e errLexEscape) Error() string        { return fmt.Sprintf(`invalid escape in string '\%c'`, e.r) }
+func (e errLexEscape) Usage() string        { return usageEscape }
+func (e errLexUTF8) Error() string          { return fmt.Sprintf("invalid UTF-8 byte: 0x%02x", e.b) }
+func (e errLexUTF8) Usage() string          { return "" }
+func (e errLexInvalidNum) Error() string    { return fmt.Sprintf("invalid number: %q", e.v) }
+func (e errLexInvalidNum) Usage() string    { return "" }
+func (e errLexInvalidDate) Error() string   { return fmt.Sprintf("invalid date: %q", e.v) }
+func (e errLexInvalidDate) Usage() string   { return "" }
+func (e errLexInlineTableNL) Error() string { return "newlines not allowed within inline tables" }
+func (e errLexInlineTableNL) Usage() string { return usageInlineNewline }
+func (e errLexStringNL) Error() string      { return "strings cannot contain newlines" }
+func (e errLexStringNL) Usage() string      { return usageStringNewline }
+func (e errParseRange) Error() string       { return fmt.Sprintf("%v is out of range for %s", e.i, e.size) }
+func (e errParseRange) Usage() string       { return usageIntOverflow }
+func (e errParseDuration) Error() string    { return fmt.Sprintf("invalid duration: %q", e.d) }
+func (e errParseDuration) Usage() string    { return usageDuration }
+
+const usageEscape = `
+A '\' inside a "-delimited string is interpreted as an escape character.
+
+The following escape sequences are supported:
+\b, \t, \n, \f, \r, \", \\, \uXXXX, and \UXXXXXXXX
+
+To prevent a '\' from being recognized as an escape character, use either:
+
+- a ' or '''-delimited string; escape characters aren't processed in them; or
+- write two backslashes to get a single backslash: '\\'.
+
+If you're trying to add a Windows path (e.g. "C:\Users\martin") then using '/'
+instead of '\' will usually also work: "C:/Users/martin".
+`
+
+const usageInlineNewline = `
+Inline tables must always be on a single line:
+
+    table = {key = 42, second = 43}
+
+It is invalid to split them over multiple lines like so:
+
+    # INVALID
+    table = {
+        key    = 42,
+        second = 43
+    }
+
+Use regular for this:
+
+    [table]
+    key    = 42
+    second = 43
+`
+
+const usageStringNewline = `
+Strings must always be on a single line, and cannot span more than one line:
+
+    # INVALID
+    string = "Hello,
+    world!"
+
+Instead use """ or ''' to split strings over multiple lines:
+
+    string = """Hello,
+    world!"""
+`
+
+const usageIntOverflow = `
+This number is too large; this may be an error in the TOML, but it can also be a
+bug in the program that uses too small of an integer.
+
+The maximum and minimum values are:
+
+    size   │ lowest         │ highest
+    ───────┼────────────────┼──────────
+    int8   │ -128           │ 127
+    int16  │ -32,768        │ 32,767
+    int32  │ -2,147,483,648 │ 2,147,483,647
+    int64  │ -9.2 × 10¹⁷    │ 9.2 × 10¹⁷
+    uint8  │ 0              │ 255
+    uint16 │ 0              │ 65535
+    uint32 │ 0              │ 4294967295
+    uint64 │ 0              │ 1.8 × 10¹⁸
+
+int refers to int32 on 32-bit systems and int64 on 64-bit systems.
+`
+
+const usageDuration = `
+A duration must be as "number<unit>", without any spaces. Valid units are:
+
+    ns         nanoseconds (billionth of a second)
+    us, µs     microseconds (millionth of a second)
+    ms         milliseconds (thousands of a second)
+    s          seconds
+    m          minutes
+    h          hours
+
+You can combine multiple units; for example "5m10s" for 5 minutes and 10
+seconds.
+`

+ 36 - 0
vendor/github.com/BurntSushi/toml/internal/tz.go

@@ -0,0 +1,36 @@
+package internal
+
+import "time"
+
+// Timezones used for local datetime, date, and time TOML types.
+//
+// The exact way times and dates without a timezone should be interpreted is not
+// well-defined in the TOML specification and left to the implementation. These
+// defaults to current local timezone offset of the computer, but this can be
+// changed by changing these variables before decoding.
+//
+// TODO:
+// Ideally we'd like to offer people the ability to configure the used timezone
+// by setting Decoder.Timezone and Encoder.Timezone; however, this is a bit
+// tricky: the reason we use three different variables for this is to support
+// round-tripping – without these specific TZ names we wouldn't know which
+// format to use.
+//
+// There isn't a good way to encode this right now though, and passing this sort
+// of information also ties in to various related issues such as string format
+// encoding, encoding of comments, etc.
+//
+// So, for the time being, just put this in internal until we can write a good
+// comprehensive API for doing all of this.
+//
+// The reason they're exported is because they're referred from in e.g.
+// internal/tag.
+//
+// Note that this behaviour is valid according to the TOML spec as the exact
+// behaviour is left up to implementations.
+var (
+	localOffset   = func() int { _, o := time.Now().Zone(); return o }()
+	LocalDatetime = time.FixedZone("datetime-local", localOffset)
+	LocalDate     = time.FixedZone("date-local", localOffset)
+	LocalTime     = time.FixedZone("time-local", localOffset)
+)

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 527 - 224
vendor/github.com/BurntSushi/toml/lex.go


+ 121 - 0
vendor/github.com/BurntSushi/toml/meta.go

@@ -0,0 +1,121 @@
+package toml
+
+import (
+	"strings"
+)
+
+// MetaData allows access to meta information about TOML data that's not
+// accessible otherwise.
+//
+// It allows checking if a key is defined in the TOML data, whether any keys
+// were undecoded, and the TOML type of a key.
+type MetaData struct {
+	context Key // Used only during decoding.
+
+	keyInfo map[string]keyInfo
+	mapping map[string]interface{}
+	keys    []Key
+	decoded map[string]struct{}
+	data    []byte // Input file; for errors.
+}
+
+// IsDefined reports if the key exists in the TOML data.
+//
+// The key should be specified hierarchically, for example to access the TOML
+// key "a.b.c" you would use IsDefined("a", "b", "c"). Keys are case sensitive.
+//
+// Returns false for an empty key.
+func (md *MetaData) IsDefined(key ...string) bool {
+	if len(key) == 0 {
+		return false
+	}
+
+	var (
+		hash      map[string]interface{}
+		ok        bool
+		hashOrVal interface{} = md.mapping
+	)
+	for _, k := range key {
+		if hash, ok = hashOrVal.(map[string]interface{}); !ok {
+			return false
+		}
+		if hashOrVal, ok = hash[k]; !ok {
+			return false
+		}
+	}
+	return true
+}
+
+// Type returns a string representation of the type of the key specified.
+//
+// Type will return the empty string if given an empty key or a key that does
+// not exist. Keys are case sensitive.
+func (md *MetaData) Type(key ...string) string {
+	if ki, ok := md.keyInfo[Key(key).String()]; ok {
+		return ki.tomlType.typeString()
+	}
+	return ""
+}
+
+// Keys returns a slice of every key in the TOML data, including key groups.
+//
+// Each key is itself a slice, where the first element is the top of the
+// hierarchy and the last is the most specific. The list will have the same
+// order as the keys appeared in the TOML data.
+//
+// All keys returned are non-empty.
+func (md *MetaData) Keys() []Key {
+	return md.keys
+}
+
+// Undecoded returns all keys that have not been decoded in the order in which
+// they appear in the original TOML document.
+//
+// This includes keys that haven't been decoded because of a [Primitive] value.
+// Once the Primitive value is decoded, the keys will be considered decoded.
+//
+// Also note that decoding into an empty interface will result in no decoding,
+// and so no keys will be considered decoded.
+//
+// In this sense, the Undecoded keys correspond to keys in the TOML document
+// that do not have a concrete type in your representation.
+func (md *MetaData) Undecoded() []Key {
+	undecoded := make([]Key, 0, len(md.keys))
+	for _, key := range md.keys {
+		if _, ok := md.decoded[key.String()]; !ok {
+			undecoded = append(undecoded, key)
+		}
+	}
+	return undecoded
+}
+
+// Key represents any TOML key, including key groups. Use [MetaData.Keys] to get
+// values of this type.
+type Key []string
+
+func (k Key) String() string {
+	ss := make([]string, len(k))
+	for i := range k {
+		ss[i] = k.maybeQuoted(i)
+	}
+	return strings.Join(ss, ".")
+}
+
+func (k Key) maybeQuoted(i int) string {
+	if k[i] == "" {
+		return `""`
+	}
+	for _, c := range k[i] {
+		if !isBareKeyChar(c, false) {
+			return `"` + dblQuotedReplacer.Replace(k[i]) + `"`
+		}
+	}
+	return k[i]
+}
+
+func (k Key) add(piece string) Key {
+	newKey := make(Key, len(k)+1)
+	copy(newKey, k)
+	newKey[len(k)] = piece
+	return newKey
+}

+ 467 - 248
vendor/github.com/BurntSushi/toml/parse.go

@@ -2,57 +2,80 @@ package toml
 
 import (
 	"fmt"
+	"os"
 	"strconv"
 	"strings"
 	"time"
-	"unicode"
 	"unicode/utf8"
+
+	"github.com/BurntSushi/toml/internal"
 )
 
 type parser struct {
-	mapping map[string]interface{}
-	types   map[string]tomlType
-	lx      *lexer
-
-	// A list of keys in the order that they appear in the TOML data.
-	ordered []Key
-
-	// the full key for the current hash in scope
-	context Key
+	lx         *lexer
+	context    Key      // Full key for the current hash in scope.
+	currentKey string   // Base key name for everything except hashes.
+	pos        Position // Current position in the TOML file.
+	tomlNext   bool
 
-	// the base key name for everything except hashes
-	currentKey string
+	ordered []Key // List of keys in the order that they appear in the TOML data.
 
-	// rough approximation of line number
-	approxLine int
-
-	// A map of 'key.group.names' to whether they were created implicitly.
-	implicits map[string]bool
+	keyInfo   map[string]keyInfo     // Map keyname → info about the TOML key.
+	mapping   map[string]interface{} // Map keyname → key value.
+	implicits map[string]struct{}    // Record implicit keys (e.g. "key.group.names").
 }
 
-type parseError string
-
-func (pe parseError) Error() string {
-	return string(pe)
+type keyInfo struct {
+	pos      Position
+	tomlType tomlType
 }
 
 func parse(data string) (p *parser, err error) {
+	_, tomlNext := os.LookupEnv("BURNTSUSHI_TOML_110")
+
 	defer func() {
 		if r := recover(); r != nil {
-			var ok bool
-			if err, ok = r.(parseError); ok {
+			if pErr, ok := r.(ParseError); ok {
+				pErr.input = data
+				err = pErr
 				return
 			}
 			panic(r)
 		}
 	}()
 
+	// Read over BOM; do this here as the lexer calls utf8.DecodeRuneInString()
+	// which mangles stuff. UTF-16 BOM isn't strictly valid, but some tools add
+	// it anyway.
+	if strings.HasPrefix(data, "\xff\xfe") || strings.HasPrefix(data, "\xfe\xff") { // UTF-16
+		data = data[2:]
+	} else if strings.HasPrefix(data, "\xef\xbb\xbf") { // UTF-8
+		data = data[3:]
+	}
+
+	// Examine first few bytes for NULL bytes; this probably means it's a UTF-16
+	// file (second byte in surrogate pair being NULL). Again, do this here to
+	// avoid having to deal with UTF-8/16 stuff in the lexer.
+	ex := 6
+	if len(data) < 6 {
+		ex = len(data)
+	}
+	if i := strings.IndexRune(data[:ex], 0); i > -1 {
+		return nil, ParseError{
+			Message:  "files cannot contain NULL bytes; probably using UTF-16; TOML files must be UTF-8",
+			Position: Position{Line: 1, Start: i, Len: 1},
+			Line:     1,
+			input:    data,
+		}
+	}
+
 	p = &parser{
+		keyInfo:   make(map[string]keyInfo),
 		mapping:   make(map[string]interface{}),
-		types:     make(map[string]tomlType),
-		lx:        lex(data),
+		lx:        lex(data, tomlNext),
 		ordered:   make([]Key, 0),
-		implicits: make(map[string]bool),
+		implicits: make(map[string]struct{}),
+		tomlNext:  tomlNext,
 	}
 	for {
 		item := p.next()
@@ -65,20 +88,57 @@ func parse(data string) (p *parser, err error) {
 	return p, nil
 }
 
+func (p *parser) panicErr(it item, err error) {
+	panic(ParseError{
+		err:      err,
+		Position: it.pos,
+		Line:     it.pos.Len,
+		LastKey:  p.current(),
+	})
+}
+
+func (p *parser) panicItemf(it item, format string, v ...interface{}) {
+	panic(ParseError{
+		Message:  fmt.Sprintf(format, v...),
+		Position: it.pos,
+		Line:     it.pos.Len,
+		LastKey:  p.current(),
+	})
+}
+
 func (p *parser) panicf(format string, v ...interface{}) {
-	msg := fmt.Sprintf("Near line %d (last key parsed '%s'): %s",
-		p.approxLine, p.current(), fmt.Sprintf(format, v...))
-	panic(parseError(msg))
+	panic(ParseError{
+		Message:  fmt.Sprintf(format, v...),
+		Position: p.pos,
+		Line:     p.pos.Line,
+		LastKey:  p.current(),
+	})
 }
 
 func (p *parser) next() item {
 	it := p.lx.nextItem()
+	//fmt.Printf("ITEM %-18s line %-3d │ %q\n", it.typ, it.pos.Line, it.val)
 	if it.typ == itemError {
-		p.panicf("%s", it.val)
+		if it.err != nil {
+			panic(ParseError{
+				Position: it.pos,
+				Line:     it.pos.Line,
+				LastKey:  p.current(),
+				err:      it.err,
+			})
+		}
+
+		p.panicItemf(it, "%s", it.val)
 	}
 	return it
 }
 
+func (p *parser) nextPos() item {
+	it := p.next()
+	p.pos = it.pos
+	return it
+}
+
 func (p *parser) bug(format string, v ...interface{}) {
 	panic(fmt.Sprintf("BUG: "+format+"\n\n", v...))
 }
@@ -97,44 +157,60 @@ func (p *parser) assertEqual(expected, got itemType) {
 
 func (p *parser) topLevel(item item) {
 	switch item.typ {
-	case itemCommentStart:
-		p.approxLine = item.line
+	case itemCommentStart: // # ..
 		p.expect(itemText)
-	case itemTableStart:
-		kg := p.next()
-		p.approxLine = kg.line
+	case itemTableStart: // [ .. ]
+		name := p.nextPos()
 
 		var key Key
-		for ; kg.typ != itemTableEnd && kg.typ != itemEOF; kg = p.next() {
-			key = append(key, p.keyString(kg))
+		for ; name.typ != itemTableEnd && name.typ != itemEOF; name = p.next() {
+			key = append(key, p.keyString(name))
 		}
-		p.assertEqual(itemTableEnd, kg.typ)
+		p.assertEqual(itemTableEnd, name.typ)
 
-		p.establishContext(key, false)
-		p.setType("", tomlHash)
+		p.addContext(key, false)
+		p.setType("", tomlHash, item.pos)
 		p.ordered = append(p.ordered, key)
-	case itemArrayTableStart:
-		kg := p.next()
-		p.approxLine = kg.line
+	case itemArrayTableStart: // [[ .. ]]
+		name := p.nextPos()
 
 		var key Key
-		for ; kg.typ != itemArrayTableEnd && kg.typ != itemEOF; kg = p.next() {
-			key = append(key, p.keyString(kg))
+		for ; name.typ != itemArrayTableEnd && name.typ != itemEOF; name = p.next() {
+			key = append(key, p.keyString(name))
 		}
-		p.assertEqual(itemArrayTableEnd, kg.typ)
+		p.assertEqual(itemArrayTableEnd, name.typ)
 
-		p.establishContext(key, true)
-		p.setType("", tomlArrayHash)
+		p.addContext(key, true)
+		p.setType("", tomlArrayHash, item.pos)
 		p.ordered = append(p.ordered, key)
-	case itemKeyStart:
-		kname := p.next()
-		p.approxLine = kname.line
-		p.currentKey = p.keyString(kname)
-
-		val, typ := p.value(p.next())
-		p.setValue(p.currentKey, val)
-		p.setType(p.currentKey, typ)
+	case itemKeyStart: // key = ..
+		outerContext := p.context
+		/// Read all the key parts (e.g. 'a' and 'b' in 'a.b')
+		k := p.nextPos()
+		var key Key
+		for ; k.typ != itemKeyEnd && k.typ != itemEOF; k = p.next() {
+			key = append(key, p.keyString(k))
+		}
+		p.assertEqual(itemKeyEnd, k.typ)
+
+		/// The current key is the last part.
+		p.currentKey = key[len(key)-1]
+
+		/// All the other parts (if any) are the context; need to set each part
+		/// as implicit.
+		context := key[:len(key)-1]
+		for i := range context {
+			p.addImplicitContext(append(p.context, context[i:i+1]...))
+		}
 		p.ordered = append(p.ordered, p.context.add(p.currentKey))
+
+		/// Set value.
+		vItem := p.next()
+		val, typ := p.value(vItem, false)
+		p.set(p.currentKey, val, typ, vItem.pos)
+
+		/// Remove the context we added (preserving any context from [tbl] lines).
+		p.context = outerContext
 		p.currentKey = ""
 	default:
 		p.bug("Unexpected type at top level: %s", item.typ)
@@ -148,180 +224,271 @@ func (p *parser) keyString(it item) string {
 		return it.val
 	case itemString, itemMultilineString,
 		itemRawString, itemRawMultilineString:
-		s, _ := p.value(it)
+		s, _ := p.value(it, false)
 		return s.(string)
 	default:
 		p.bug("Unexpected key type: %s", it.typ)
-		panic("unreachable")
 	}
+	panic("unreachable")
 }
 
+var datetimeRepl = strings.NewReplacer(
+	"z", "Z",
+	"t", "T",
+	" ", "T")
+
 // value translates an expected value from the lexer into a Go value wrapped
 // as an empty interface.
-func (p *parser) value(it item) (interface{}, tomlType) {
+func (p *parser) value(it item, parentIsArray bool) (interface{}, tomlType) {
 	switch it.typ {
 	case itemString:
-		return p.replaceEscapes(it.val), p.typeOfPrimitive(it)
+		return p.replaceEscapes(it, it.val), p.typeOfPrimitive(it)
 	case itemMultilineString:
-		trimmed := stripFirstNewline(stripEscapedWhitespace(it.val))
-		return p.replaceEscapes(trimmed), p.typeOfPrimitive(it)
+		return p.replaceEscapes(it, p.stripEscapedNewlines(stripFirstNewline(it.val))), p.typeOfPrimitive(it)
 	case itemRawString:
 		return it.val, p.typeOfPrimitive(it)
 	case itemRawMultilineString:
 		return stripFirstNewline(it.val), p.typeOfPrimitive(it)
+	case itemInteger:
+		return p.valueInteger(it)
+	case itemFloat:
+		return p.valueFloat(it)
 	case itemBool:
 		switch it.val {
 		case "true":
 			return true, p.typeOfPrimitive(it)
 		case "false":
 			return false, p.typeOfPrimitive(it)
+		default:
+			p.bug("Expected boolean value, but got '%s'.", it.val)
 		}
-		p.bug("Expected boolean value, but got '%s'.", it.val)
-	case itemInteger:
-		if !numUnderscoresOK(it.val) {
-			p.panicf("Invalid integer %q: underscores must be surrounded by digits",
-				it.val)
-		}
-		val := strings.Replace(it.val, "_", "", -1)
-		num, err := strconv.ParseInt(val, 10, 64)
-		if err != nil {
-			// Distinguish integer values. Normally, it'd be a bug if the lexer
-			// provides an invalid integer, but it's possible that the number is
-			// out of range of valid values (which the lexer cannot determine).
-			// So mark the former as a bug but the latter as a legitimate user
-			// error.
-			if e, ok := err.(*strconv.NumError); ok &&
-				e.Err == strconv.ErrRange {
-
-				p.panicf("Integer '%s' is out of the range of 64-bit "+
-					"signed integers.", it.val)
-			} else {
-				p.bug("Expected integer value, but got '%s'.", it.val)
-			}
+	case itemDatetime:
+		return p.valueDatetime(it)
+	case itemArray:
+		return p.valueArray(it)
+	case itemInlineTableStart:
+		return p.valueInlineTable(it, parentIsArray)
+	default:
+		p.bug("Unexpected value type: %s", it.typ)
+	}
+	panic("unreachable")
+}
+
+func (p *parser) valueInteger(it item) (interface{}, tomlType) {
+	if !numUnderscoresOK(it.val) {
+		p.panicItemf(it, "Invalid integer %q: underscores must be surrounded by digits", it.val)
+	}
+	if numHasLeadingZero(it.val) {
+		p.panicItemf(it, "Invalid integer %q: cannot have leading zeroes", it.val)
+	}
+
+	num, err := strconv.ParseInt(it.val, 0, 64)
+	if err != nil {
+		// Distinguish integer values. Normally, it'd be a bug if the lexer
+		// provides an invalid integer, but it's possible that the number is
+		// out of range of valid values (which the lexer cannot determine).
+		// So mark the former as a bug but the latter as a legitimate user
+		// error.
+		if e, ok := err.(*strconv.NumError); ok && e.Err == strconv.ErrRange {
+			p.panicErr(it, errParseRange{i: it.val, size: "int64"})
+		} else {
+			p.bug("Expected integer value, but got '%s'.", it.val)
 		}
-		return num, p.typeOfPrimitive(it)
-	case itemFloat:
-		parts := strings.FieldsFunc(it.val, func(r rune) bool {
-			switch r {
-			case '.', 'e', 'E':
-				return true
-			}
-			return false
-		})
-		for _, part := range parts {
-			if !numUnderscoresOK(part) {
-				p.panicf("Invalid float %q: underscores must be "+
-					"surrounded by digits", it.val)
-			}
+	}
+	return num, p.typeOfPrimitive(it)
+}
+
+func (p *parser) valueFloat(it item) (interface{}, tomlType) {
+	parts := strings.FieldsFunc(it.val, func(r rune) bool {
+		switch r {
+		case '.', 'e', 'E':
+			return true
 		}
-		if !numPeriodsOK(it.val) {
-			// As a special case, numbers like '123.' or '1.e2',
-			// which are valid as far as Go/strconv are concerned,
-			// must be rejected because TOML says that a fractional
-			// part consists of '.' followed by 1+ digits.
-			p.panicf("Invalid float %q: '.' must be followed "+
-				"by one or more digits", it.val)
-		}
-		val := strings.Replace(it.val, "_", "", -1)
-		num, err := strconv.ParseFloat(val, 64)
-		if err != nil {
-			if e, ok := err.(*strconv.NumError); ok &&
-				e.Err == strconv.ErrRange {
-
-				p.panicf("Float '%s' is out of the range of 64-bit "+
-					"IEEE-754 floating-point numbers.", it.val)
-			} else {
-				p.panicf("Invalid float value: %q", it.val)
-			}
+		return false
+	})
+	for _, part := range parts {
+		if !numUnderscoresOK(part) {
+			p.panicItemf(it, "Invalid float %q: underscores must be surrounded by digits", it.val)
 		}
-		return num, p.typeOfPrimitive(it)
-	case itemDatetime:
-		var t time.Time
-		var ok bool
-		var err error
-		for _, format := range []string{
-			"2006-01-02T15:04:05Z07:00",
-			"2006-01-02T15:04:05",
-			"2006-01-02",
-		} {
-			t, err = time.ParseInLocation(format, it.val, time.Local)
-			if err == nil {
-				ok = true
-				break
-			}
+	}
+	if len(parts) > 0 && numHasLeadingZero(parts[0]) {
+		p.panicItemf(it, "Invalid float %q: cannot have leading zeroes", it.val)
+	}
+	if !numPeriodsOK(it.val) {
+		// As a special case, numbers like '123.' or '1.e2',
+		// which are valid as far as Go/strconv are concerned,
+		// must be rejected because TOML says that a fractional
+		// part consists of '.' followed by 1+ digits.
+		p.panicItemf(it, "Invalid float %q: '.' must be followed by one or more digits", it.val)
+	}
+	val := strings.Replace(it.val, "_", "", -1)
+	if val == "+nan" || val == "-nan" { // Go doesn't support this, but TOML spec does.
+		val = "nan"
+	}
+	num, err := strconv.ParseFloat(val, 64)
+	if err != nil {
+		if e, ok := err.(*strconv.NumError); ok && e.Err == strconv.ErrRange {
+			p.panicErr(it, errParseRange{i: it.val, size: "float64"})
+		} else {
+			p.panicItemf(it, "Invalid float value: %q", it.val)
 		}
-		if !ok {
-			p.panicf("Invalid TOML Datetime: %q.", it.val)
+	}
+	return num, p.typeOfPrimitive(it)
+}
+
+var dtTypes = []struct {
+	fmt  string
+	zone *time.Location
+	next bool
+}{
+	{time.RFC3339Nano, time.Local, false},
+	{"2006-01-02T15:04:05.999999999", internal.LocalDatetime, false},
+	{"2006-01-02", internal.LocalDate, false},
+	{"15:04:05.999999999", internal.LocalTime, false},
+
+	// tomlNext
+	{"2006-01-02T15:04Z07:00", time.Local, true},
+	{"2006-01-02T15:04", internal.LocalDatetime, true},
+	{"15:04", internal.LocalTime, true},
+}
+
+func (p *parser) valueDatetime(it item) (interface{}, tomlType) {
+	it.val = datetimeRepl.Replace(it.val)
+	var (
+		t   time.Time
+		ok  bool
+		err error
+	)
+	for _, dt := range dtTypes {
+		if dt.next && !p.tomlNext {
+			continue
 		}
-		return t, p.typeOfPrimitive(it)
-	case itemArray:
-		array := make([]interface{}, 0)
-		types := make([]tomlType, 0)
+		t, err = time.ParseInLocation(dt.fmt, it.val, dt.zone)
+		if err == nil {
+			ok = true
+			break
+		}
+	}
+	if !ok {
+		p.panicItemf(it, "Invalid TOML Datetime: %q.", it.val)
+	}
+	return t, p.typeOfPrimitive(it)
+}
 
-		for it = p.next(); it.typ != itemArrayEnd; it = p.next() {
-			if it.typ == itemCommentStart {
-				p.expect(itemText)
-				continue
-			}
+func (p *parser) valueArray(it item) (interface{}, tomlType) {
+	p.setType(p.currentKey, tomlArray, it.pos)
+
+	var (
+		types []tomlType
 
-			val, typ := p.value(it)
-			array = append(array, val)
-			types = append(types, typ)
+		// Initialize to a non-nil empty slice. This makes it consistent with
+		// how S = [] decodes into a non-nil slice inside something like struct
+		// { S []string }. See #338
+		array = []interface{}{}
+	)
+	for it = p.next(); it.typ != itemArrayEnd; it = p.next() {
+		if it.typ == itemCommentStart {
+			p.expect(itemText)
+			continue
 		}
-		return array, p.typeOfArray(types)
-	case itemInlineTableStart:
-		var (
-			hash         = make(map[string]interface{})
-			outerContext = p.context
-			outerKey     = p.currentKey
-		)
 
-		p.context = append(p.context, p.currentKey)
-		p.currentKey = ""
-		for it := p.next(); it.typ != itemInlineTableEnd; it = p.next() {
-			if it.typ != itemKeyStart {
-				p.bug("Expected key start but instead found %q, around line %d",
-					it.val, p.approxLine)
-			}
-			if it.typ == itemCommentStart {
-				p.expect(itemText)
-				continue
-			}
+		val, typ := p.value(it, true)
+		array = append(array, val)
+		types = append(types, typ)
+
+		// XXX: types isn't used here, we need it to record the accurate type
+		// information.
+		//
+		// Not entirely sure how to best store this; could use "key[0]",
+		// "key[1]" notation, or maybe store it on the Array type?
+		_ = types
+	}
+	return array, tomlArray
+}
+
+func (p *parser) valueInlineTable(it item, parentIsArray bool) (interface{}, tomlType) {
+	var (
+		hash         = make(map[string]interface{})
+		outerContext = p.context
+		outerKey     = p.currentKey
+	)
+
+	p.context = append(p.context, p.currentKey)
+	prevContext := p.context
+	p.currentKey = ""
 
-			// retrieve key
-			k := p.next()
-			p.approxLine = k.line
-			kname := p.keyString(k)
+	p.addImplicit(p.context)
+	p.addContext(p.context, parentIsArray)
 
-			// retrieve value
-			p.currentKey = kname
-			val, typ := p.value(p.next())
-			// make sure we keep metadata up to date
-			p.setType(kname, typ)
-			p.ordered = append(p.ordered, p.context.add(p.currentKey))
-			hash[kname] = val
+	/// Loop over all table key/value pairs.
+	for it := p.next(); it.typ != itemInlineTableEnd; it = p.next() {
+		if it.typ == itemCommentStart {
+			p.expect(itemText)
+			continue
 		}
-		p.context = outerContext
-		p.currentKey = outerKey
-		return hash, tomlHash
+
+		/// Read all key parts.
+		k := p.nextPos()
+		var key Key
+		for ; k.typ != itemKeyEnd && k.typ != itemEOF; k = p.next() {
+			key = append(key, p.keyString(k))
+		}
+		p.assertEqual(itemKeyEnd, k.typ)
+
+		/// The current key is the last part.
+		p.currentKey = key[len(key)-1]
+
+		/// All the other parts (if any) are the context; need to set each part
+		/// as implicit.
+		context := key[:len(key)-1]
+		for i := range context {
+			p.addImplicitContext(append(p.context, context[i:i+1]...))
+		}
+		p.ordered = append(p.ordered, p.context.add(p.currentKey))
+
+		/// Set the value.
+		val, typ := p.value(p.next(), false)
+		p.set(p.currentKey, val, typ, it.pos)
+		hash[p.currentKey] = val
+
+		/// Restore context.
+		p.context = prevContext
 	}
-	p.bug("Unexpected value type: %s", it.typ)
-	panic("unreachable")
+	p.context = outerContext
+	p.currentKey = outerKey
+	return hash, tomlHash
+}
+
+// numHasLeadingZero checks if this number has leading zeroes, allowing for '0',
+// +/- signs, and base prefixes.
+func numHasLeadingZero(s string) bool {
+	if len(s) > 1 && s[0] == '0' && !(s[1] == 'b' || s[1] == 'o' || s[1] == 'x') { // Allow 0b, 0o, 0x
+		return true
+	}
+	if len(s) > 2 && (s[0] == '-' || s[0] == '+') && s[1] == '0' {
+		return true
+	}
+	return false
 }
 
 // numUnderscoresOK checks whether each underscore in s is surrounded by
 // characters that are not underscores.
 func numUnderscoresOK(s string) bool {
+	switch s {
+	case "nan", "+nan", "-nan", "inf", "-inf", "+inf":
+		return true
+	}
 	accept := false
 	for _, r := range s {
 		if r == '_' {
 			if !accept {
 				return false
 			}
-			accept = false
-			continue
 		}
-		accept = true
+
+		// isHexadecimal is a superset of all the permissable characters
+		// surrounding an underscore.
+		accept = isHexadecimal(r)
 	}
 	return accept
 }
@@ -338,13 +505,12 @@ func numPeriodsOK(s string) bool {
 	return !period
 }
 
-// establishContext sets the current context of the parser,
-// where the context is either a hash or an array of hashes. Which one is
-// set depends on the value of the `array` parameter.
+// Set the current context of the parser, where the context is either a hash or
+// an array of hashes, depending on the value of the `array` parameter.
 //
 // Establishing the context also makes sure that the key isn't a duplicate, and
 // will create implicit hashes automatically.
-func (p *parser) establishContext(key Key, array bool) {
+func (p *parser) addContext(key Key, array bool) {
 	var ok bool
 
 	// Always start at the top level and drill down for our context.
@@ -383,7 +549,7 @@ func (p *parser) establishContext(key Key, array bool) {
 		// list of tables for it.
 		k := key[len(key)-1]
 		if _, ok := hashContext[k]; !ok {
-			hashContext[k] = make([]map[string]interface{}, 0, 5)
+			hashContext[k] = make([]map[string]interface{}, 0, 4)
 		}
 
 		// Add a new table. But make sure the key hasn't already been used
@@ -391,8 +557,7 @@ func (p *parser) establishContext(key Key, array bool) {
 		if hash, ok := hashContext[k].([]map[string]interface{}); ok {
 			hashContext[k] = append(hash, make(map[string]interface{}))
 		} else {
-			p.panicf("Key '%s' was already created and cannot be used as "+
-				"an array.", keyContext)
+			p.panicf("Key '%s' was already created and cannot be used as an array.", key)
 		}
 	} else {
 		p.setValue(key[len(key)-1], make(map[string]interface{}))
@@ -400,15 +565,22 @@ func (p *parser) establishContext(key Key, array bool) {
 	p.context = append(p.context, key[len(key)-1])
 }
 
+// set calls setValue and setType.
+func (p *parser) set(key string, val interface{}, typ tomlType, pos Position) {
+	p.setValue(key, val)
+	p.setType(key, typ, pos)
+}
+
 // setValue sets the given key to the given value in the current context.
 // It will make sure that the key hasn't already been defined, account for
 // implicit key groups.
 func (p *parser) setValue(key string, value interface{}) {
-	var tmpHash interface{}
-	var ok bool
-
-	hash := p.mapping
-	keyContext := make(Key, 0)
+	var (
+		tmpHash    interface{}
+		ok         bool
+		hash       = p.mapping
+		keyContext Key
+	)
 	for _, k := range p.context {
 		keyContext = append(keyContext, k)
 		if tmpHash, ok = hash[k]; !ok {
@@ -422,24 +594,26 @@ func (p *parser) setValue(key string, value interface{}) {
 		case map[string]interface{}:
 			hash = t
 		default:
-			p.bug("Expected hash to have type 'map[string]interface{}', but "+
-				"it has '%T' instead.", tmpHash)
+			p.panicf("Key '%s' has already been defined.", keyContext)
 		}
 	}
 	keyContext = append(keyContext, key)
 
 	if _, ok := hash[key]; ok {
-		// Typically, if the given key has already been set, then we have
-		// to raise an error since duplicate keys are disallowed. However,
-		// it's possible that a key was previously defined implicitly. In this
-		// case, it is allowed to be redefined concretely. (See the
-		// `tests/valid/implicit-and-explicit-after.toml` test in `toml-test`.)
+		// Normally redefining keys isn't allowed, but the key could have been
+		// defined implicitly and it's allowed to be redefined concretely. (See
+		// the `valid/implicit-and-explicit-after.toml` in toml-test)
 		//
 		// But we have to make sure to stop marking it as an implicit. (So that
 		// another redefinition provokes an error.)
 		//
 		// Note that since it has already been defined (as a hash), we don't
 		// want to overwrite it. So our business is done.
+		if p.isArray(keyContext) {
+			p.removeImplicit(keyContext)
+			hash[key] = value
+			return
+		}
 		if p.isImplicit(keyContext) {
 			p.removeImplicit(keyContext)
 			return
@@ -449,41 +623,37 @@ func (p *parser) setValue(key string, value interface{}) {
 		// key, which is *always* wrong.
 		p.panicf("Key '%s' has already been defined.", keyContext)
 	}
+
 	hash[key] = value
 }
 
-// setType sets the type of a particular value at a given key.
-// It should be called immediately AFTER setValue.
+// setType sets the type of a particular value at a given key. It should be
+// called immediately AFTER setValue.
 //
 // Note that if `key` is empty, then the type given will be applied to the
 // current context (which is either a table or an array of tables).
-func (p *parser) setType(key string, typ tomlType) {
+func (p *parser) setType(key string, typ tomlType, pos Position) {
 	keyContext := make(Key, 0, len(p.context)+1)
-	for _, k := range p.context {
-		keyContext = append(keyContext, k)
-	}
+	keyContext = append(keyContext, p.context...)
 	if len(key) > 0 { // allow type setting for hashes
 		keyContext = append(keyContext, key)
 	}
-	p.types[keyContext.String()] = typ
-}
-
-// addImplicit sets the given Key as having been created implicitly.
-func (p *parser) addImplicit(key Key) {
-	p.implicits[key.String()] = true
-}
-
-// removeImplicit stops tagging the given key as having been implicitly
-// created.
-func (p *parser) removeImplicit(key Key) {
-	p.implicits[key.String()] = false
+	// Special case to make empty keys ("" = 1) work.
+	// Without it it will set "" rather than `""`.
+	// TODO: why is this needed? And why is this only needed here?
+	if len(keyContext) == 0 {
+		keyContext = Key{""}
+	}
+	p.keyInfo[keyContext.String()] = keyInfo{tomlType: typ, pos: pos}
 }
 
-// isImplicit returns true if the key group pointed to by the key was created
-// implicitly.
-func (p *parser) isImplicit(key Key) bool {
-	return p.implicits[key.String()]
-}
+// Implicit keys need to be created when tables are implied in "a.b.c.d = 1" and
+// "[a.b.c]" (the "a", "b", and "c" hashes are never created explicitly).
+func (p *parser) addImplicit(key Key)        { p.implicits[key.String()] = struct{}{} }
+func (p *parser) removeImplicit(key Key)     { delete(p.implicits, key.String()) }
+func (p *parser) isImplicit(key Key) bool    { _, ok := p.implicits[key.String()]; return ok }
+func (p *parser) isArray(key Key) bool       { return p.keyInfo[key.String()].tomlType == tomlArray }
+func (p *parser) addImplicitContext(key Key) { p.addImplicit(key); p.addContext(key, false) }
 
 // current returns the full key name of the current context.
 func (p *parser) current() string {
@@ -497,24 +667,67 @@ func (p *parser) current() string {
 }
 
 func stripFirstNewline(s string) string {
-	if len(s) == 0 || s[0] != '\n' {
-		return s
+	if len(s) > 0 && s[0] == '\n' {
+		return s[1:]
+	}
+	if len(s) > 1 && s[0] == '\r' && s[1] == '\n' {
+		return s[2:]
 	}
-	return s[1:]
+	return s
 }
 
-func stripEscapedWhitespace(s string) string {
-	esc := strings.Split(s, "\\\n")
-	if len(esc) > 1 {
-		for i := 1; i < len(esc); i++ {
-			esc[i] = strings.TrimLeftFunc(esc[i], unicode.IsSpace)
+// stripEscapedNewlines removes whitespace after line-ending backslashes in
+// multiline strings.
+//
+// A line-ending backslash is an unescaped \ followed only by whitespace until
+// the next newline. After a line-ending backslash, all whitespace is removed
+// until the next non-whitespace character.
+func (p *parser) stripEscapedNewlines(s string) string {
+	var b strings.Builder
+	var i int
+	for {
+		ix := strings.Index(s[i:], `\`)
+		if ix < 0 {
+			b.WriteString(s)
+			return b.String()
+		}
+		i += ix
+
+		if len(s) > i+1 && s[i+1] == '\\' {
+			// Escaped backslash.
+			i += 2
+			continue
+		}
+		// Scan until the next non-whitespace.
+		j := i + 1
+	whitespaceLoop:
+		for ; j < len(s); j++ {
+			switch s[j] {
+			case ' ', '\t', '\r', '\n':
+			default:
+				break whitespaceLoop
+			}
 		}
+		if j == i+1 {
+			// Not a whitespace escape.
+			i++
+			continue
+		}
+		if !strings.Contains(s[i:j], "\n") {
+			// This is not a line-ending backslash.
+			// (It's a bad escape sequence, but we can let
+			// replaceEscapes catch it.)
+			i++
+			continue
+		}
+		b.WriteString(s[:i])
+		s = s[j:]
+		i = 0
 	}
-	return strings.Join(esc, "")
 }
 
-func (p *parser) replaceEscapes(str string) string {
-	var replaced []rune
+func (p *parser) replaceEscapes(it item, str string) string {
+	replaced := make([]rune, 0, len(str))
 	s := []byte(str)
 	r := 0
 	for r < len(s) {
@@ -532,7 +745,8 @@ func (p *parser) replaceEscapes(str string) string {
 		switch s[r] {
 		default:
 			p.bug("Expected valid escape code after \\, but got %q.", s[r])
-			return ""
+		case ' ', '\t':
+			p.panicItemf(it, "invalid escape: '\\%c'", s[r])
 		case 'b':
 			replaced = append(replaced, rune(0x0008))
 			r += 1
@@ -548,24 +762,35 @@ func (p *parser) replaceEscapes(str string) string {
 		case 'r':
 			replaced = append(replaced, rune(0x000D))
 			r += 1
+		case 'e':
+			if p.tomlNext {
+				replaced = append(replaced, rune(0x001B))
+				r += 1
+			}
 		case '"':
 			replaced = append(replaced, rune(0x0022))
 			r += 1
 		case '\\':
 			replaced = append(replaced, rune(0x005C))
 			r += 1
+		case 'x':
+			if p.tomlNext {
+				escaped := p.asciiEscapeToUnicode(it, s[r+1:r+3])
+				replaced = append(replaced, escaped)
+				r += 3
+			}
 		case 'u':
 			// At this point, we know we have a Unicode escape of the form
 			// `uXXXX` at [r, r+5). (Because the lexer guarantees this
 			// for us.)
-			escaped := p.asciiEscapeToUnicode(s[r+1 : r+5])
+			escaped := p.asciiEscapeToUnicode(it, s[r+1:r+5])
 			replaced = append(replaced, escaped)
 			r += 5
 		case 'U':
 			// At this point, we know we have a Unicode escape of the form
 			// `uXXXX` at [r, r+9). (Because the lexer guarantees this
 			// for us.)
-			escaped := p.asciiEscapeToUnicode(s[r+1 : r+9])
+			escaped := p.asciiEscapeToUnicode(it, s[r+1:r+9])
 			replaced = append(replaced, escaped)
 			r += 9
 		}
@@ -573,20 +798,14 @@ func (p *parser) replaceEscapes(str string) string {
 	return string(replaced)
 }
 
-func (p *parser) asciiEscapeToUnicode(bs []byte) rune {
+func (p *parser) asciiEscapeToUnicode(it item, bs []byte) rune {
 	s := string(bs)
 	hex, err := strconv.ParseUint(strings.ToLower(s), 16, 32)
 	if err != nil {
-		p.bug("Could not parse '%s' as a hexadecimal number, but the "+
-			"lexer claims it's OK: %s", s, err)
+		p.bug("Could not parse '%s' as a hexadecimal number, but the lexer claims it's OK: %s", s, err)
 	}
 	if !utf8.ValidRune(rune(hex)) {
-		p.panicf("Escaped character '\\u%s' is not valid UTF-8.", s)
+		p.panicItemf(it, "Escaped character '\\u%s' is not valid UTF-8.", s)
 	}
 	return rune(hex)
 }
-
-func isStringType(ty itemType) bool {
-	return ty == itemString || ty == itemMultilineString ||
-		ty == itemRawString || ty == itemRawMultilineString
-}

+ 0 - 1
vendor/github.com/BurntSushi/toml/session.vim

@@ -1 +0,0 @@
-au BufWritePost *.go silent!make tags > /dev/null 2>&1

+ 0 - 91
vendor/github.com/BurntSushi/toml/type_check.go

@@ -1,91 +0,0 @@
-package toml
-
-// tomlType represents any Go type that corresponds to a TOML type.
-// While the first draft of the TOML spec has a simplistic type system that
-// probably doesn't need this level of sophistication, we seem to be militating
-// toward adding real composite types.
-type tomlType interface {
-	typeString() string
-}
-
-// typeEqual accepts any two types and returns true if they are equal.
-func typeEqual(t1, t2 tomlType) bool {
-	if t1 == nil || t2 == nil {
-		return false
-	}
-	return t1.typeString() == t2.typeString()
-}
-
-func typeIsHash(t tomlType) bool {
-	return typeEqual(t, tomlHash) || typeEqual(t, tomlArrayHash)
-}
-
-type tomlBaseType string
-
-func (btype tomlBaseType) typeString() string {
-	return string(btype)
-}
-
-func (btype tomlBaseType) String() string {
-	return btype.typeString()
-}
-
-var (
-	tomlInteger   tomlBaseType = "Integer"
-	tomlFloat     tomlBaseType = "Float"
-	tomlDatetime  tomlBaseType = "Datetime"
-	tomlString    tomlBaseType = "String"
-	tomlBool      tomlBaseType = "Bool"
-	tomlArray     tomlBaseType = "Array"
-	tomlHash      tomlBaseType = "Hash"
-	tomlArrayHash tomlBaseType = "ArrayHash"
-)
-
-// typeOfPrimitive returns a tomlType of any primitive value in TOML.
-// Primitive values are: Integer, Float, Datetime, String and Bool.
-//
-// Passing a lexer item other than the following will cause a BUG message
-// to occur: itemString, itemBool, itemInteger, itemFloat, itemDatetime.
-func (p *parser) typeOfPrimitive(lexItem item) tomlType {
-	switch lexItem.typ {
-	case itemInteger:
-		return tomlInteger
-	case itemFloat:
-		return tomlFloat
-	case itemDatetime:
-		return tomlDatetime
-	case itemString:
-		return tomlString
-	case itemMultilineString:
-		return tomlString
-	case itemRawString:
-		return tomlString
-	case itemRawMultilineString:
-		return tomlString
-	case itemBool:
-		return tomlBool
-	}
-	p.bug("Cannot infer primitive type of lex item '%s'.", lexItem)
-	panic("unreachable")
-}
-
-// typeOfArray returns a tomlType for an array given a list of types of its
-// values.
-//
-// In the current spec, if an array is homogeneous, then its type is always
-// "Array". If the array is not homogeneous, an error is generated.
-func (p *parser) typeOfArray(types []tomlType) tomlType {
-	// Empty arrays are cool.
-	if len(types) == 0 {
-		return tomlArray
-	}
-
-	theType := types[0]
-	for _, t := range types[1:] {
-		if !typeEqual(theType, t) {
-			p.panicf("Array contains values of type '%s' and '%s', but "+
-				"arrays must be homogeneous.", theType, t)
-		}
-	}
-	return tomlArray
-}

+ 2 - 2
vendor/github.com/BurntSushi/toml/type_fields.go

@@ -70,8 +70,8 @@ func typeFields(t reflect.Type) []field {
 	next := []field{{typ: t}}
 
 	// Count of queued names for current level and the next.
-	count := map[reflect.Type]int{}
-	nextCount := map[reflect.Type]int{}
+	var count map[reflect.Type]int
+	var nextCount map[reflect.Type]int
 
 	// Types already visited at an earlier level.
 	visited := map[reflect.Type]bool{}

+ 70 - 0
vendor/github.com/BurntSushi/toml/type_toml.go

@@ -0,0 +1,70 @@
+package toml
+
+// tomlType represents any Go type that corresponds to a TOML type.
+// While the first draft of the TOML spec has a simplistic type system that
+// probably doesn't need this level of sophistication, we seem to be militating
+// toward adding real composite types.
+type tomlType interface {
+	typeString() string
+}
+
+// typeEqual accepts any two types and returns true if they are equal.
+func typeEqual(t1, t2 tomlType) bool {
+	if t1 == nil || t2 == nil {
+		return false
+	}
+	return t1.typeString() == t2.typeString()
+}
+
+func typeIsTable(t tomlType) bool {
+	return typeEqual(t, tomlHash) || typeEqual(t, tomlArrayHash)
+}
+
+type tomlBaseType string
+
+func (btype tomlBaseType) typeString() string {
+	return string(btype)
+}
+
+func (btype tomlBaseType) String() string {
+	return btype.typeString()
+}
+
+var (
+	tomlInteger   tomlBaseType = "Integer"
+	tomlFloat     tomlBaseType = "Float"
+	tomlDatetime  tomlBaseType = "Datetime"
+	tomlString    tomlBaseType = "String"
+	tomlBool      tomlBaseType = "Bool"
+	tomlArray     tomlBaseType = "Array"
+	tomlHash      tomlBaseType = "Hash"
+	tomlArrayHash tomlBaseType = "ArrayHash"
+)
+
+// typeOfPrimitive returns a tomlType of any primitive value in TOML.
+// Primitive values are: Integer, Float, Datetime, String and Bool.
+//
+// Passing a lexer item other than the following will cause a BUG message
+// to occur: itemString, itemBool, itemInteger, itemFloat, itemDatetime.
+func (p *parser) typeOfPrimitive(lexItem item) tomlType {
+	switch lexItem.typ {
+	case itemInteger:
+		return tomlInteger
+	case itemFloat:
+		return tomlFloat
+	case itemDatetime:
+		return tomlDatetime
+	case itemString:
+		return tomlString
+	case itemMultilineString:
+		return tomlString
+	case itemRawString:
+		return tomlString
+	case itemRawMultilineString:
+		return tomlString
+	case itemBool:
+		return tomlBool
+	}
+	p.bug("Cannot infer primitive type of lex item '%s'.", lexItem)
+	panic("unreachable")
+}

+ 21 - 0
vendor/github.com/CloudyKit/fastprinter/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 CloudyKit
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 2 - 0
vendor/github.com/CloudyKit/fastprinter/README.md

@@ -0,0 +1,2 @@
+# fastprinter
+FastPrinter supports write values in io.Writer without allocation

+ 369 - 0
vendor/github.com/CloudyKit/fastprinter/decimal.go

@@ -0,0 +1,369 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Multiprecision decimal numbers.
+// For floating-point formatting only; not general purpose.
+// Only operations are assign and (binary) left/right shift.
+// Can do binary floating point in multiprecision decimal precisely
+// because 2 divides 10; cannot do decimal floating point
+// in multiprecision binary precisely.
+
+package fastprinter
+
+type decimal struct {
+	d     [800]byte // digits, big-endian representation
+	nd    int       // number of digits used
+	dp    int       // decimal point
+	neg   bool
+	trunc bool // discarded nonzero digits beyond d[:nd]
+}
+
+// trim trailing zeros from number.
+// (They are meaningless; the decimal point is tracked
+// independent of the number of digits.)
+func trim(a *decimal) {
+	for a.nd > 0 && a.d[a.nd-1] == '0' {
+		a.nd--
+	}
+	if a.nd == 0 {
+		a.dp = 0
+	}
+}
+
+// Assign v to a.
+func (a *decimal) Assign(v uint64) {
+	var buf [24]byte
+
+	// Write reversed decimal in buf.
+	n := 0
+	for v > 0 {
+		v1 := v / 10
+		v -= 10 * v1
+		buf[n] = byte(v + '0')
+		n++
+		v = v1
+	}
+
+	// Reverse again to produce forward decimal in a.d.
+	a.nd = 0
+	for n--; n >= 0; n-- {
+		a.d[a.nd] = buf[n]
+		a.nd++
+	}
+	a.dp = a.nd
+	trim(a)
+}
+
+// Maximum shift that we can do in one pass without overflow.
+// A uint has 32 or 64 bits, and we have to be able to accommodate 9<<k.
+const uintSize = 32 << (^uint(0) >> 63)
+const maxShift = uintSize - 4
+
+// Binary shift right (/ 2) by k bits.  k <= maxShift to avoid overflow.
+func rightShift(a *decimal, k uint) {
+	r := 0 // read pointer
+	w := 0 // write pointer
+
+	// Pick up enough leading digits to cover first shift.
+	var n uint
+	for ; n>>k == 0; r++ {
+		if r >= a.nd {
+			if n == 0 {
+				// a == 0; shouldn't get here, but handle anyway.
+				a.nd = 0
+				return
+			}
+			for n>>k == 0 {
+				n = n * 10
+				r++
+			}
+			break
+		}
+		c := uint(a.d[r])
+		n = n*10 + c - '0'
+	}
+	a.dp -= r - 1
+
+	// Pick up a digit, put down a digit.
+	for ; r < a.nd; r++ {
+		c := uint(a.d[r])
+		dig := n >> k
+		n -= dig << k
+		a.d[w] = byte(dig + '0')
+		w++
+		n = n*10 + c - '0'
+	}
+
+	// Put down extra digits.
+	for n > 0 {
+		dig := n >> k
+		n -= dig << k
+		if w < len(a.d) {
+			a.d[w] = byte(dig + '0')
+			w++
+		} else if dig > 0 {
+			a.trunc = true
+		}
+		n = n * 10
+	}
+
+	a.nd = w
+	trim(a)
+}
+
+// Cheat sheet for left shift: table indexed by shift count giving
+// number of new digits that will be introduced by that shift.
+//
+// For example, leftcheats[4] = {2, "625"}.  That means that
+// if we are shifting by 4 (multiplying by 16), it will add 2 digits
+// when the string prefix is "625" through "999", and one fewer digit
+// if the string prefix is "000" through "624".
+//
+// Credit for this trick goes to Ken.
+
+type leftCheat struct {
+	delta  int    // number of new digits
+	cutoff string // minus one digit if original < a.
+}
+
+var leftcheats = []leftCheat{
+	// Leading digits of 1/2^i = 5^i.
+	// 5^23 is not an exact 64-bit floating point number,
+	// so have to use bc for the math.
+	// Go up to 60 to be large enough for 32bit and 64bit platforms.
+	/*
+		seq 60 | sed 's/^/5^/' | bc |
+		awk 'BEGIN{ print "\t{ 0, \"\" }," }
+		{
+			log2 = log(2)/log(10)
+			printf("\t{ %d, \"%s\" },\t// * %d\n",
+				int(log2*NR+1), $0, 2**NR)
+		}'
+	*/
+	{0, ""},
+	{1, "5"},                                           // * 2
+	{1, "25"},                                          // * 4
+	{1, "125"},                                         // * 8
+	{2, "625"},                                         // * 16
+	{2, "3125"},                                        // * 32
+	{2, "15625"},                                       // * 64
+	{3, "78125"},                                       // * 128
+	{3, "390625"},                                      // * 256
+	{3, "1953125"},                                     // * 512
+	{4, "9765625"},                                     // * 1024
+	{4, "48828125"},                                    // * 2048
+	{4, "244140625"},                                   // * 4096
+	{4, "1220703125"},                                  // * 8192
+	{5, "6103515625"},                                  // * 16384
+	{5, "30517578125"},                                 // * 32768
+	{5, "152587890625"},                                // * 65536
+	{6, "762939453125"},                                // * 131072
+	{6, "3814697265625"},                               // * 262144
+	{6, "19073486328125"},                              // * 524288
+	{7, "95367431640625"},                              // * 1048576
+	{7, "476837158203125"},                             // * 2097152
+	{7, "2384185791015625"},                            // * 4194304
+	{7, "11920928955078125"},                           // * 8388608
+	{8, "59604644775390625"},                           // * 16777216
+	{8, "298023223876953125"},                          // * 33554432
+	{8, "1490116119384765625"},                         // * 67108864
+	{9, "7450580596923828125"},                         // * 134217728
+	{9, "37252902984619140625"},                        // * 268435456
+	{9, "186264514923095703125"},                       // * 536870912
+	{10, "931322574615478515625"},                      // * 1073741824
+	{10, "4656612873077392578125"},                     // * 2147483648
+	{10, "23283064365386962890625"},                    // * 4294967296
+	{10, "116415321826934814453125"},                   // * 8589934592
+	{11, "582076609134674072265625"},                   // * 17179869184
+	{11, "2910383045673370361328125"},                  // * 34359738368
+	{11, "14551915228366851806640625"},                 // * 68719476736
+	{12, "72759576141834259033203125"},                 // * 137438953472
+	{12, "363797880709171295166015625"},                // * 274877906944
+	{12, "1818989403545856475830078125"},               // * 549755813888
+	{13, "9094947017729282379150390625"},               // * 1099511627776
+	{13, "45474735088646411895751953125"},              // * 2199023255552
+	{13, "227373675443232059478759765625"},             // * 4398046511104
+	{13, "1136868377216160297393798828125"},            // * 8796093022208
+	{14, "5684341886080801486968994140625"},            // * 17592186044416
+	{14, "28421709430404007434844970703125"},           // * 35184372088832
+	{14, "142108547152020037174224853515625"},          // * 70368744177664
+	{15, "710542735760100185871124267578125"},          // * 140737488355328
+	{15, "3552713678800500929355621337890625"},         // * 281474976710656
+	{15, "17763568394002504646778106689453125"},        // * 562949953421312
+	{16, "88817841970012523233890533447265625"},        // * 1125899906842624
+	{16, "444089209850062616169452667236328125"},       // * 2251799813685248
+	{16, "2220446049250313080847263336181640625"},      // * 4503599627370496
+	{16, "11102230246251565404236316680908203125"},     // * 9007199254740992
+	{17, "55511151231257827021181583404541015625"},     // * 18014398509481984
+	{17, "277555756156289135105907917022705078125"},    // * 36028797018963968
+	{17, "1387778780781445675529539585113525390625"},   // * 72057594037927936
+	{18, "6938893903907228377647697925567626953125"},   // * 144115188075855872
+	{18, "34694469519536141888238489627838134765625"},  // * 288230376151711744
+	{18, "173472347597680709441192448139190673828125"}, // * 576460752303423488
+	{19, "867361737988403547205962240695953369140625"}, // * 1152921504606846976
+}
+
+// Is the leading prefix of b lexicographically less than s?
+func prefixIsLessThan(b []byte, s string) bool {
+	for i := 0; i < len(s); i++ {
+		if i >= len(b) {
+			return true
+		}
+		if b[i] != s[i] {
+			return b[i] < s[i]
+		}
+	}
+	return false
+}
+
+// Binary shift left (* 2) by k bits.  k <= maxShift to avoid overflow.
+func leftShift(a *decimal, k uint) {
+	delta := leftcheats[k].delta
+	if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) {
+		delta--
+	}
+
+	r := a.nd         // read index
+	w := a.nd + delta // write index
+
+	// Pick up a digit, put down a digit.
+	var n uint
+	for r--; r >= 0; r-- {
+		n += (uint(a.d[r]) - '0') << k
+		quo := n / 10
+		rem := n - 10*quo
+		w--
+		if w < len(a.d) {
+			a.d[w] = byte(rem + '0')
+		} else if rem != 0 {
+			a.trunc = true
+		}
+		n = quo
+	}
+
+	// Put down extra digits.
+	for n > 0 {
+		quo := n / 10
+		rem := n - 10*quo
+		w--
+		if w < len(a.d) {
+			a.d[w] = byte(rem + '0')
+		} else if rem != 0 {
+			a.trunc = true
+		}
+		n = quo
+	}
+
+	a.nd += delta
+	if a.nd >= len(a.d) {
+		a.nd = len(a.d)
+	}
+	a.dp += delta
+	trim(a)
+}
+
+// Binary shift left (k > 0) or right (k < 0).
+func (a *decimal) Shift(k int) {
+	switch {
+	case a.nd == 0:
+	// nothing to do: a == 0
+	case k > 0:
+		for k > maxShift {
+			leftShift(a, maxShift)
+			k -= maxShift
+		}
+		leftShift(a, uint(k))
+	case k < 0:
+		for k < -maxShift {
+			rightShift(a, maxShift)
+			k += maxShift
+		}
+		rightShift(a, uint(-k))
+	}
+}
+
+// If we chop a at nd digits, should we round up?
+func shouldRoundUp(a *decimal, nd int) bool {
+	if nd < 0 || nd >= a.nd {
+		return false
+	}
+	if a.d[nd] == '5' && nd+1 == a.nd {
+		// exactly halfway - round to even
+		// if we truncated, a little higher than what's recorded - always round up
+		if a.trunc {
+			return true
+		}
+		return nd > 0 && (a.d[nd-1]-'0')%2 != 0
+	}
+	// not halfway - digit tells all
+	return a.d[nd] >= '5'
+}
+
+// Round a to nd digits (or fewer).
+// If nd is zero, it means we're rounding
+// just to the left of the digits, as in
+// 0.09 -> 0.1.
+func (a *decimal) Round(nd int) {
+	if nd < 0 || nd >= a.nd {
+		return
+	}
+	if shouldRoundUp(a, nd) {
+		a.RoundUp(nd)
+	} else {
+		a.RoundDown(nd)
+	}
+}
+
+// Round a down to nd digits (or fewer).
+func (a *decimal) RoundDown(nd int) {
+	if nd < 0 || nd >= a.nd {
+		return
+	}
+	a.nd = nd
+	trim(a)
+}
+
+// Round a up to nd digits (or fewer).
+func (a *decimal) RoundUp(nd int) {
+	if nd < 0 || nd >= a.nd {
+		return
+	}
+
+	// round up
+	for i := nd - 1; i >= 0; i-- {
+		c := a.d[i]
+		if c < '9' {
+			// can stop after this digit
+			a.d[i]++
+			a.nd = i + 1
+			return
+		}
+	}
+
+	// Number is all 9s.
+	// Change to single 1 with adjusted decimal point.
+	a.d[0] = '1'
+	a.nd = 1
+	a.dp++
+}
+
+// Extract integer part, rounded appropriately.
+// No guarantees about overflow.
+func (a *decimal) RoundedInteger() uint64 {
+	if a.dp > 20 {
+		return 0xFFFFFFFFFFFFFFFF
+	}
+	var i int
+	n := uint64(0)
+	for i = 0; i < a.dp && i < a.nd; i++ {
+		n = n*10 + uint64(a.d[i]-'0')
+	}
+	for ; i < a.dp; i++ {
+		n *= 10
+	}
+	if shouldRoundUp(a, a.dp) {
+		n++
+	}
+	return n
+}

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است