huangyan 1 жил өмнө
commit
ff14ff36d7
11 өөрчлөгдсөн 5143 нэмэгдсэн , 0 устгасан
  1. 8 0
      .idea/.gitignore
  2. 9 0
      .idea/exhook-svr-go.iml
  3. 8 0
      .idea/modules.xml
  4. 37 0
      README.md
  5. 15 0
      go.mod
  6. 120 0
      go.sum
  7. 110 0
      main.go
  8. 3455 0
      protobuf/exhook.pb.go
  9. 499 0
      protobuf/exhook.proto
  10. 825 0
      protobuf/exhook_grpc.pb.go
  11. 57 0
      utils/counter.go

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 9 - 0
.idea/exhook-svr-go.iml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="Go" enabled="true" />
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/exhook-svr-go.iml" filepath="$PROJECT_DIR$/.idea/exhook-svr-go.iml" />
+    </modules>
+  </component>
+</project>

+ 37 - 0
README.md

@@ -0,0 +1,37 @@
+# exhook-svr-go
+
+This is a demo server written in go for exhook
+
+## Prerequisites
+
+- [Go](https://golang.org) (any one of the three latest major)
+- [Protocol buffer](https://developers.google.com/protocol-buffers) **compiler**, `protoc`
+    For installation instructions, see
+    [Protocol Buffer Compiler Installation](https://grpc.io/docs/protoc-installation/).
+- **Go plugins** for the protocol compiler:
+    - Install the protocol compiler plugins for Go using the following commands:
+    ```
+    export GO111MODULE=on  # Enable module mode
+    go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
+    go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
+    ```
+
+    - Update your PATH so that the protoc compiler can find the plugins:
+    ```
+    export PATH="$PATH:$(go env GOPATH)/bin"
+    ```
+
+## Run
+
+Try to compile the `*.proto` files:
+
+```
+protoc --go_out=. --go_opt=paths=source_relative \
+    --go-grpc_out=. --go-grpc_opt=paths=source_relative \
+    protobuf/exhook.proto
+```
+
+Run server
+```
+go run main.go
+```

+ 15 - 0
go.mod

@@ -0,0 +1,15 @@
+module emqx.io/grpc/exhook
+
+go 1.11
+
+replace emqx.io/grpc/exhook => ./
+
+require (
+	github.com/bytedance/sonic v1.11.6 // indirect
+	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da
+	github.com/golang/protobuf v1.5.0
+	github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
+	github.com/pkg/errors v0.9.1 // indirect
+	google.golang.org/grpc v1.36.0
+	google.golang.org/protobuf v1.27.1
+)

+ 120 - 0
go.sum

@@ -0,0 +1,120 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
+github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
+github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
+github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
+github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
+github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
+github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+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.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+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.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+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.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
+github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
+github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+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/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+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.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
+github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+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/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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+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/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/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/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/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 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+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.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.36.0 h1:o1bcQ6imQMIOpdrO3SWf2z5RV72WbDwdXuK0MDlc8As=
+google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+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.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.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
+google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+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=
+nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

+ 110 - 0
main.go

@@ -0,0 +1,110 @@
+package main
+
+import (
+	"context"
+	pb "emqx.io/grpc/exhook/protobuf"
+	"encoding/json"
+	"fmt"
+	"github.com/patrickmn/go-cache"
+	"github.com/pkg/errors"
+	"google.golang.org/grpc"
+	"log"
+	"net"
+	"strings"
+	"time"
+)
+
+const (
+	port = ":9000"
+)
+
+var cacheInstance = cache.New(5*time.Minute, 10*time.Minute)
+
+type server struct {
+	pb.UnimplementedHookProviderServer
+}
+
+func (s *server) OnProviderLoaded(ctx context.Context, in *pb.ProviderLoadedRequest) (*pb.LoadedResponse, error) {
+	hooks := []*pb.HookSpec{
+		{Name: "message.publish"},
+	}
+	return &pb.LoadedResponse{Hooks: hooks}, nil
+}
+
+func (s *server) OnMessagePublish(ctx context.Context, in *pb.MessagePublishRequest) (*pb.ValuedResponse, error) {
+	log.Printf("[DEBUG] OnMessagePublish: %s", in.Message.Topic)
+	topic := strings.TrimSuffix(in.GetMessage().GetTopic(), "/")
+	payload := in.GetMessage().GetPayload()
+
+	if payload == nil || len(payload) >= 1000 {
+		return nil, errors.New("消息体为空或大于等于1000字节")
+	}
+
+	var jsonPayload map[string]interface{}
+	if err := json.Unmarshal(payload, &jsonPayload); err != nil {
+		return nil, errors.Wrap(err, "json解析失败")
+	}
+
+	typeVal, ok := jsonPayload["type"].(float64)
+	if !ok {
+		return nil, errors.New("json中'type'字段解析失败")
+	}
+
+	if int(typeVal) == 2 {
+		key := fmt.Sprintf("%s-%v", topic, jsonPayload["data"])
+		log.Printf("缓存中键的值: %s", key)
+		if _, found := cacheInstance.Get(key); found {
+			return discardMessagePublish(ctx, in, func(response *pb.ValuedResponse) error {
+				log.Printf("丢弃重复消息")
+				return nil
+			})
+		}
+		cacheInstance.Set(key, "alarm", cache.DefaultExpiration)
+	}
+
+	// 正常发送消息
+	return &pb.ValuedResponse{
+		Type: pb.ValuedResponse_STOP_AND_RETURN,
+		Value: &pb.ValuedResponse_Message{
+			Message: in.GetMessage(),
+		},
+	}, nil
+}
+
+func discardMessagePublish(ctx context.Context, in *pb.MessagePublishRequest, responseWriter func(*pb.ValuedResponse) error) (*pb.ValuedResponse, error) {
+	emptyPayload := []byte{}
+	newMsg := &pb.Message{
+		Id:      in.Message.Id,
+		Node:    in.Message.Node,
+		From:    in.Message.From,
+		Topic:   in.Message.Topic,
+		Payload: emptyPayload,
+		Headers: map[string]string{"allow_publish": "false"},
+	}
+
+	reply := &pb.ValuedResponse{
+		Type: pb.ValuedResponse_STOP_AND_RETURN,
+		Value: &pb.ValuedResponse_Message{
+			Message: newMsg,
+		},
+	}
+
+	if err := responseWriter(reply); err != nil {
+		return nil, errors.Wrap(err, "发送响应时出错")
+	}
+
+	return reply, nil
+}
+
+func main() {
+	lis, err := net.Listen("tcp", port)
+	if err != nil {
+		log.Fatalf("failed to listen: %v", err)
+	}
+	s := grpc.NewServer()
+	pb.RegisterHookProviderServer(s, &server{})
+	log.Println("Started gRPC server on", port)
+	if err := s.Serve(lis); err != nil {
+		log.Fatalf("failed to serve: %v", err)
+	}
+}

+ 3455 - 0
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.28.1
+// 	protoc        v3.18.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
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;
+}

+ 825 - 0
protobuf/exhook_grpc.pb.go

@@ -0,0 +1,825 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.2.0
+// - protoc             v3.18.1
+// source: protobuf/exhook.proto
+
+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
+
+// 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, "/emqx.exhook.v2.HookProvider/OnProviderLoaded", 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, "/emqx.exhook.v2.HookProvider/OnProviderUnloaded", 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, "/emqx.exhook.v2.HookProvider/OnClientConnect", 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, "/emqx.exhook.v2.HookProvider/OnClientConnack", 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, "/emqx.exhook.v2.HookProvider/OnClientConnected", 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, "/emqx.exhook.v2.HookProvider/OnClientDisconnected", 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, "/emqx.exhook.v2.HookProvider/OnClientAuthenticate", 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, "/emqx.exhook.v2.HookProvider/OnClientAuthorize", 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, "/emqx.exhook.v2.HookProvider/OnClientSubscribe", 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, "/emqx.exhook.v2.HookProvider/OnClientUnsubscribe", 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, "/emqx.exhook.v2.HookProvider/OnSessionCreated", 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, "/emqx.exhook.v2.HookProvider/OnSessionSubscribed", 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, "/emqx.exhook.v2.HookProvider/OnSessionUnsubscribed", 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, "/emqx.exhook.v2.HookProvider/OnSessionResumed", 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, "/emqx.exhook.v2.HookProvider/OnSessionDiscarded", 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, "/emqx.exhook.v2.HookProvider/OnSessionTakenover", 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, "/emqx.exhook.v2.HookProvider/OnSessionTerminated", 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, "/emqx.exhook.v2.HookProvider/OnMessagePublish", 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, "/emqx.exhook.v2.HookProvider/OnMessageDelivered", 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, "/emqx.exhook.v2.HookProvider/OnMessageDropped", 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, "/emqx.exhook.v2.HookProvider/OnMessageAcked", 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: "/emqx.exhook.v2.HookProvider/OnProviderLoaded",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnProviderUnloaded",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnClientConnect",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnClientConnack",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnClientConnected",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnClientDisconnected",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnClientAuthenticate",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnClientAuthorize",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnClientSubscribe",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnClientUnsubscribe",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnSessionCreated",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnSessionSubscribed",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnSessionUnsubscribed",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnSessionResumed",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnSessionDiscarded",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnSessionTakenover",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnSessionTerminated",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnMessagePublish",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnMessageDelivered",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnMessageDropped",
+	}
+	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: "/emqx.exhook.v2.HookProvider/OnMessageAcked",
+	}
+	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",
+}

+ 57 - 0
utils/counter.go

@@ -0,0 +1,57 @@
+package exhook
+
+import (
+	"math"
+	"sync"
+	"time"
+)
+
+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
+}