This is an automated email from the ASF dual-hosted git repository.

dmwangnima pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git


The following commit(s) were added to refs/heads/main by this push:
     new 7683ea455 feat: add reflection service (#2522)
7683ea455 is described below

commit 7683ea455a60752ca4b5912654f228a04bb0b297
Author: finalt <[email protected]>
AuthorDate: Sat Dec 2 10:53:20 2023 +0800

    feat: add reflection service (#2522)
    
    * add reflection service
    
    * add license
    
    * fix lint
    
    * fix lint
    
    * fix lint
    
    * update license
    
    * fix comment
    
    * rename reflection.proto
    
    * ignore license
    
    * fix lint
    
    * update proto
    
    ---------
    
    Co-authored-by: Ken Liu <[email protected]>
---
 Makefile                                           |   2 +-
 config/provider_config.go                          |  56 +-
 imports/imports.go                                 |   4 +-
 protocol/triple/health/healthServer.go             |   1 +
 .../internal/client/reflection_client/main.go      | 125 +++
 protocol/triple/reflection/serverreflection.go     | 285 ++++++
 .../reflection/triple_reflection/reflection.pb.go  | 956 +++++++++++++++++++++
 .../reflection/triple_reflection/reflection.proto  | 141 +++
 .../triple_reflection/reflection.triple.go         | 199 +++++
 protocol/triple/server.go                          |  50 +-
 protocol/triple/triple.go                          |   1 +
 11 files changed, 1786 insertions(+), 34 deletions(-)

diff --git a/Makefile b/Makefile
index 33dcf68c8..e322a004e 100644
--- a/Makefile
+++ b/Makefile
@@ -63,7 +63,7 @@ deps: prepare
 
 .PHONY: license
 license: clean prepareLic
-       $(GO_LICENSE_CHECKER) -v -a -r -i 
vendor,protocol/triple/triple_protocol,cmd/protoc-gen-go-triple/internal 
$(LICENSE_DIR)/license.txt . go && [[ -z `git status -s` ]]
+       $(GO_LICENSE_CHECKER) -v -a -r -i 
vendor,protocol/triple/triple_protocol,protocol/triple/reflection,cmd/protoc-gen-go-triple/internal
 $(LICENSE_DIR)/license.txt . go && [[ -z `git status -s` ]]
 
 .PHONY: verify
 verify: clean license test
diff --git a/config/provider_config.go b/config/provider_config.go
index 7bbb90a58..67889303a 100644
--- a/config/provider_config.go
+++ b/config/provider_config.go
@@ -27,8 +27,6 @@ import (
 
        "github.com/dubbogo/gost/log/logger"
 
-       tripleConstant "github.com/dubbogo/triple/pkg/common/constant"
-
        perrors "github.com/pkg/errors"
 )
 
@@ -123,33 +121,33 @@ func (c *ProviderConfig) Init(rc *RootConfig) error {
                serviceConfig.adaptiveService = c.AdaptiveService
        }
 
-       for k, v := range rc.Protocols {
-               if v.Name == tripleConstant.TRIPLE {
-                       // Auto create grpc based health check service.
-                       //healthService := NewServiceConfigBuilder().
-                       //      SetProtocolIDs(k).
-                       //      SetNotRegister(true).
-                       //      
SetInterface(constant.HealthCheckServiceInterface).
-                       //      Build()
-                       //if err := healthService.Init(rc); err != nil {
-                       //      return err
-                       //}
-                       //c.Services[constant.HealthCheckServiceTypeName] = 
healthService
-
-                       // Auto create reflection service configure only when 
provider with triple service is configured.
-                       tripleReflectionService := NewServiceConfigBuilder().
-                               SetProtocolIDs(k).
-                               SetNotRegister(true).
-                               
SetInterface(constant.ReflectionServiceInterface).
-                               Build()
-                       if err := tripleReflectionService.Init(rc); err != nil {
-                               return err
-                       }
-                       // Maybe only register once, If setting this service, 
break from traversing Protocols.
-                       c.Services[constant.ReflectionServiceTypeName] = 
tripleReflectionService
-                       break
-               }
-       }
+       //for k, v := range rc.Protocols {
+       //      if v.Name == tripleConstant.TRIPLE {
+       //              // Auto create grpc based health check service.
+       //              healthService := NewServiceConfigBuilder().
+       //                      SetProtocolIDs(k).
+       //                      SetNotRegister(true).
+       //                      
SetInterface(constant.HealthCheckServiceInterface).
+       //                      Build()
+       //              if err := healthService.Init(rc); err != nil {
+       //                      return err
+       //              }
+       //              c.Services[constant.HealthCheckServiceTypeName] = 
healthService
+       //
+       //              // Auto create reflection service configure only when 
provider with triple service is configured.
+       //              tripleReflectionService := NewServiceConfigBuilder().
+       //                      SetProtocolIDs(k).
+       //                      SetNotRegister(true).
+       //                      
SetInterface(constant.ReflectionServiceInterface).
+       //                      Build()
+       //              if err := tripleReflectionService.Init(rc); err != nil {
+       //                      return err
+       //              }
+       //              // Maybe only register once, If setting this service, 
break from traversing Protocols.
+       //              c.Services[constant.ReflectionServiceTypeName] = 
tripleReflectionService
+       //              break
+       //      }
+       //}
 
        if err := c.check(); err != nil {
                return err
diff --git a/imports/imports.go b/imports/imports.go
index 906aced10..39a7197b1 100644
--- a/imports/imports.go
+++ b/imports/imports.go
@@ -72,13 +72,11 @@ import (
        _ "dubbo.apache.org/dubbo-go/v3/otel/trace/stdout"
        _ "dubbo.apache.org/dubbo-go/v3/otel/trace/zipkin"
        _ "dubbo.apache.org/dubbo-go/v3/protocol/dubbo"
-       _ "dubbo.apache.org/dubbo-go/v3/protocol/dubbo3"
-       _ "dubbo.apache.org/dubbo-go/v3/protocol/dubbo3/reflection"
-       _ "dubbo.apache.org/dubbo-go/v3/protocol/grpc"
        _ "dubbo.apache.org/dubbo-go/v3/protocol/jsonrpc"
        _ "dubbo.apache.org/dubbo-go/v3/protocol/rest"
        _ "dubbo.apache.org/dubbo-go/v3/protocol/triple"
        _ "dubbo.apache.org/dubbo-go/v3/protocol/triple/health"
+       _ "dubbo.apache.org/dubbo-go/v3/protocol/triple/reflection"
        _ "dubbo.apache.org/dubbo-go/v3/proxy/proxy_factory"
        _ "dubbo.apache.org/dubbo-go/v3/registry/directory"
        _ "dubbo.apache.org/dubbo-go/v3/registry/etcdv3"
diff --git a/protocol/triple/health/healthServer.go 
b/protocol/triple/health/healthServer.go
index 43b515af3..7ec228c4e 100644
--- a/protocol/triple/health/healthServer.go
+++ b/protocol/triple/health/healthServer.go
@@ -168,6 +168,7 @@ func init() {
        server.SetProServices(&server.ServiceDefinition{
                Handler: healthServer,
                Info:    &triple_health.Health_ServiceInfo,
+               Opts:    []server.ServiceOption{server.WithNotRegister()},
        })
 }
 
diff --git a/protocol/triple/internal/client/reflection_client/main.go 
b/protocol/triple/internal/client/reflection_client/main.go
new file mode 100644
index 000000000..036dc2717
--- /dev/null
+++ b/protocol/triple/internal/client/reflection_client/main.go
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+       "context"
+)
+
+import (
+       "github.com/dubbogo/gost/log/logger"
+
+       "github.com/golang/protobuf/proto"
+
+       "google.golang.org/protobuf/types/descriptorpb"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3/client"
+       _ "dubbo.apache.org/dubbo-go/v3/imports"
+       reflection 
"dubbo.apache.org/dubbo-go/v3/protocol/triple/reflection/triple_reflection"
+)
+
+func main() {
+       cli, err := client.NewClient(
+               client.WithClientURL("tri://127.0.0.1:20000"),
+       )
+       if err != nil {
+               panic(err)
+       }
+       svc, err := reflection.NewServerReflection(cli)
+       if err != nil {
+               panic(err)
+       }
+       stream, err := svc.ServerReflectionInfo(context.Background())
+       if err != nil {
+               panic(err)
+       }
+       testReflection(stream)
+}
+
+func testReflection(stream 
reflection.ServerReflection_ServerReflectionInfoClient) {
+       if err := testFileByFilename(stream); err != nil {
+               logger.Error(err)
+       }
+       if err := testFileContainingSymbol(stream); err != nil {
+               logger.Error(err)
+       }
+       if err := testListServices(stream); err != nil {
+               logger.Error(err)
+       }
+       if err := stream.CloseRequest(); err != nil {
+               logger.Error(err)
+       }
+       if err := stream.CloseResponse(); err != nil {
+               logger.Error(err)
+       }
+}
+
+func testFileByFilename(stream 
reflection.ServerReflection_ServerReflectionInfoClient) error {
+       logger.Info("start to test call FileByFilename")
+       if err := stream.Send(&reflection.ServerReflectionRequest{
+               MessageRequest: 
&reflection.ServerReflectionRequest_FileByFilename{FileByFilename: 
"reflection.proto"},
+       }); err != nil {
+               return err
+       }
+       recv, err := stream.Recv()
+       if err != nil {
+               return err
+       }
+       m := new(descriptorpb.FileDescriptorProto)
+       if err = 
proto.Unmarshal(recv.GetFileDescriptorResponse().GetFileDescriptorProto()[0], 
m); err != nil {
+               return err
+       }
+       logger.Infof("call FileByFilename 's resp : %s", m)
+       return nil
+}
+
+func testFileContainingSymbol(stream 
reflection.ServerReflection_ServerReflectionInfoClient) error {
+       logger.Info("start to test call FileContainingSymbol")
+       if err := stream.Send(&reflection.ServerReflectionRequest{
+               MessageRequest: 
&reflection.ServerReflectionRequest_FileContainingSymbol{FileContainingSymbol: 
"dubbo.reflection.v1alpha.ServerReflection"},
+       }); err != nil {
+               return err
+       }
+       recv, err := stream.Recv()
+       if err != nil {
+               return err
+       }
+       m := new(descriptorpb.FileDescriptorProto)
+       if err = 
proto.Unmarshal(recv.GetFileDescriptorResponse().GetFileDescriptorProto()[0], 
m); err != nil {
+               return err
+       }
+       logger.Infof("call FileContainingSymbol 's resp : %s", m)
+       return nil
+}
+
+func testListServices(stream 
reflection.ServerReflection_ServerReflectionInfoClient) error {
+       logger.Info("start to test call ListServices")
+       if err := stream.Send(&reflection.ServerReflectionRequest{
+               MessageRequest: 
&reflection.ServerReflectionRequest_ListServices{},
+       }); err != nil {
+               return err
+       }
+       recv, err := stream.Recv()
+       if err != nil {
+               return err
+       }
+       logger.Infof("call ListServices 's resp : %s", 
recv.GetListServicesResponse().GetService())
+       return nil
+}
diff --git a/protocol/triple/reflection/serverreflection.go 
b/protocol/triple/reflection/serverreflection.go
new file mode 100644
index 000000000..de2816b33
--- /dev/null
+++ b/protocol/triple/reflection/serverreflection.go
@@ -0,0 +1,285 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package reflection
+
+import (
+       "context"
+       "io"
+       "sort"
+)
+
+import (
+       "google.golang.org/grpc"
+       "google.golang.org/grpc/codes"
+       "google.golang.org/grpc/status"
+
+       "google.golang.org/protobuf/proto"
+
+       "google.golang.org/protobuf/reflect/protodesc"
+       "google.golang.org/protobuf/reflect/protoreflect"
+       "google.golang.org/protobuf/reflect/protoregistry"
+)
+
+import (
+       rpb 
"dubbo.apache.org/dubbo-go/v3/protocol/triple/reflection/triple_reflection"
+       "dubbo.apache.org/dubbo-go/v3/server"
+)
+
+// ServiceInfoProvider is an interface used to retrieve metadata about the
+// services to expose.
+//
+// The reflection service is only interested in the service names, but the
+// signature is this way so that *grpc.Server implements it. So it is okay
+// for a custom implementation to return zero values for the
+// grpc.ServiceInfo values in the map.
+//
+// # Experimental
+//
+// Notice: This type is EXPERIMENTAL and may be changed or removed in a
+// later release.
+type ServiceInfoProvider interface {
+       GetServiceInfo() map[string]grpc.ServiceInfo
+}
+
+// ExtensionResolver is the interface used to query details about extensions.
+// This interface is satisfied by protoregistry.GlobalTypes.
+//
+// # Experimental
+//
+// Notice: This type is EXPERIMENTAL and may be changed or removed in a
+// later release.
+type ExtensionResolver interface {
+       protoregistry.ExtensionTypeResolver
+       RangeExtensionsByMessage(message protoreflect.FullName, f 
func(protoreflect.ExtensionType) bool)
+}
+
+func NewServer() *ReflectionServer {
+       return &ReflectionServer{
+               descResolver: protoregistry.GlobalFiles,
+               extResolver:  protoregistry.GlobalTypes,
+       }
+}
+
+type ReflectionServer struct {
+       s            ServiceInfoProvider
+       descResolver protodesc.Resolver
+       extResolver  ExtensionResolver
+}
+
+// fileDescWithDependencies returns a slice of serialized fileDescriptors in
+// wire format ([]byte). The fileDescriptors will include fd and all the
+// transitive dependencies of fd with names not in sentFileDescriptors.
+func (s *ReflectionServer) fileDescWithDependencies(fd 
protoreflect.FileDescriptor, sentFileDescriptors map[string]bool) ([][]byte, 
error) {
+       if fd.IsPlaceholder() {
+               // If the given root file is a placeholder, treat it
+               // as missing instead of serializing it.
+               return nil, protoregistry.NotFound
+       }
+       var r [][]byte
+       queue := []protoreflect.FileDescriptor{fd}
+       for len(queue) > 0 {
+               currentfd := queue[0]
+               queue = queue[1:]
+               if currentfd.IsPlaceholder() {
+                       // Skip any missing files in the dependency graph.
+                       continue
+               }
+               if sent := sentFileDescriptors[currentfd.Path()]; len(r) == 0 
|| !sent {
+                       sentFileDescriptors[currentfd.Path()] = true
+                       fdProto := protodesc.ToFileDescriptorProto(currentfd)
+                       currentfdEncoded, err := proto.Marshal(fdProto)
+                       if err != nil {
+                               return nil, err
+                       }
+                       r = append(r, currentfdEncoded)
+               }
+               for i := 0; i < currentfd.Imports().Len(); i++ {
+                       queue = append(queue, currentfd.Imports().Get(i))
+               }
+       }
+       return r, nil
+}
+
+// fileDescEncodingContainingSymbol finds the file descriptor containing the
+// given symbol, finds all of its previously unsent transitive dependencies,
+// does marshaling on them, and returns the marshaled result. The given symbol
+// can be a type, a service or a method.
+func (s *ReflectionServer) fileDescEncodingContainingSymbol(name string, 
sentFileDescriptors map[string]bool) ([][]byte, error) {
+       d, err := 
s.descResolver.FindDescriptorByName(protoreflect.FullName(name))
+       if err != nil {
+               return nil, err
+       }
+       return s.fileDescWithDependencies(d.ParentFile(), sentFileDescriptors)
+}
+
+// fileDescEncodingContainingExtension finds the file descriptor containing
+// given extension, finds all of its previously unsent transitive dependencies,
+// does marshaling on them, and returns the marshaled result.
+func (s *ReflectionServer) fileDescEncodingContainingExtension(typeName 
string, extNum int32, sentFileDescriptors map[string]bool) ([][]byte, error) {
+       xt, err := 
s.extResolver.FindExtensionByNumber(protoreflect.FullName(typeName), 
protoreflect.FieldNumber(extNum))
+       if err != nil {
+               return nil, err
+       }
+       return s.fileDescWithDependencies(xt.TypeDescriptor().ParentFile(), 
sentFileDescriptors)
+}
+
+// allExtensionNumbersForTypeName returns all extension numbers for the given 
type.
+func (s *ReflectionServer) allExtensionNumbersForTypeName(name string) 
([]int32, error) {
+       var numbers []int32
+       s.extResolver.RangeExtensionsByMessage(protoreflect.FullName(name), 
func(xt protoreflect.ExtensionType) bool {
+               numbers = append(numbers, int32(xt.TypeDescriptor().Number()))
+               return true
+       })
+       sort.Slice(numbers, func(i, j int) bool {
+               return numbers[i] < numbers[j]
+       })
+       if len(numbers) == 0 {
+               // maybe return an error if given type name is not known
+               if _, err := 
s.descResolver.FindDescriptorByName(protoreflect.FullName(name)); err != nil {
+                       return nil, err
+               }
+       }
+       return numbers, nil
+}
+
+// listServices returns the names of services this server exposes.
+func (s *ReflectionServer) listServices() []*rpb.ServiceResponse {
+       serviceInfo := s.s.GetServiceInfo()
+       resp := make([]*rpb.ServiceResponse, 0, len(serviceInfo))
+       for svc := range serviceInfo {
+               resp = append(resp, &rpb.ServiceResponse{Name: svc})
+       }
+       sort.Slice(resp, func(i, j int) bool {
+               return resp[i].Name < resp[j].Name
+       })
+       return resp
+}
+
+// ServerReflectionInfo is the reflection service handler.
+func (s *ReflectionServer) ServerReflectionInfo(ctx context.Context, stream 
rpb.ServerReflection_ServerReflectionInfoServer) error {
+       sentFileDescriptors := make(map[string]bool)
+       for {
+               in, err := stream.Recv()
+               if err == io.EOF {
+                       return nil
+               }
+               if err != nil {
+                       return err
+               }
+
+               out := &rpb.ServerReflectionResponse{
+                       ValidHost:       in.Host,
+                       OriginalRequest: in,
+               }
+               switch req := in.MessageRequest.(type) {
+               case *rpb.ServerReflectionRequest_FileByFilename:
+                       var b [][]byte
+                       fd, err := 
s.descResolver.FindFileByPath(req.FileByFilename)
+                       if err == nil {
+                               b, err = s.fileDescWithDependencies(fd, 
sentFileDescriptors)
+                       }
+                       if err != nil {
+                               out.MessageResponse = 
&rpb.ServerReflectionResponse_ErrorResponse{
+                                       ErrorResponse: &rpb.ErrorResponse{
+                                               ErrorCode:    
int32(codes.NotFound),
+                                               ErrorMessage: err.Error(),
+                                       },
+                               }
+                       } else {
+                               out.MessageResponse = 
&rpb.ServerReflectionResponse_FileDescriptorResponse{
+                                       FileDescriptorResponse: 
&rpb.FileDescriptorResponse{FileDescriptorProto: b},
+                               }
+                       }
+               case *rpb.ServerReflectionRequest_FileContainingSymbol:
+                       b, err := 
s.fileDescEncodingContainingSymbol(req.FileContainingSymbol, 
sentFileDescriptors)
+                       if err != nil {
+                               out.MessageResponse = 
&rpb.ServerReflectionResponse_ErrorResponse{
+                                       ErrorResponse: &rpb.ErrorResponse{
+                                               ErrorCode:    
int32(codes.NotFound),
+                                               ErrorMessage: err.Error(),
+                                       },
+                               }
+                       } else {
+                               out.MessageResponse = 
&rpb.ServerReflectionResponse_FileDescriptorResponse{
+                                       FileDescriptorResponse: 
&rpb.FileDescriptorResponse{FileDescriptorProto: b},
+                               }
+                       }
+               case *rpb.ServerReflectionRequest_FileContainingExtension:
+                       typeName := req.FileContainingExtension.ContainingType
+                       extNum := req.FileContainingExtension.ExtensionNumber
+                       b, err := 
s.fileDescEncodingContainingExtension(typeName, extNum, sentFileDescriptors)
+                       if err != nil {
+                               out.MessageResponse = 
&rpb.ServerReflectionResponse_ErrorResponse{
+                                       ErrorResponse: &rpb.ErrorResponse{
+                                               ErrorCode:    
int32(codes.NotFound),
+                                               ErrorMessage: err.Error(),
+                                       },
+                               }
+                       } else {
+                               out.MessageResponse = 
&rpb.ServerReflectionResponse_FileDescriptorResponse{
+                                       FileDescriptorResponse: 
&rpb.FileDescriptorResponse{FileDescriptorProto: b},
+                               }
+                       }
+               case *rpb.ServerReflectionRequest_AllExtensionNumbersOfType:
+                       extNums, err := 
s.allExtensionNumbersForTypeName(req.AllExtensionNumbersOfType)
+                       if err != nil {
+                               out.MessageResponse = 
&rpb.ServerReflectionResponse_ErrorResponse{
+                                       ErrorResponse: &rpb.ErrorResponse{
+                                               ErrorCode:    
int32(codes.NotFound),
+                                               ErrorMessage: err.Error(),
+                                       },
+                               }
+                       } else {
+                               out.MessageResponse = 
&rpb.ServerReflectionResponse_AllExtensionNumbersResponse{
+                                       AllExtensionNumbersResponse: 
&rpb.ExtensionNumberResponse{
+                                               BaseTypeName:    
req.AllExtensionNumbersOfType,
+                                               ExtensionNumber: extNums,
+                                       },
+                               }
+                       }
+               case *rpb.ServerReflectionRequest_ListServices:
+                       out.MessageResponse = 
&rpb.ServerReflectionResponse_ListServicesResponse{
+                               ListServicesResponse: &rpb.ListServiceResponse{
+                                       Service: s.listServices(),
+                               },
+                       }
+               default:
+                       return status.Errorf(codes.InvalidArgument, "invalid 
MessageRequest: %v", in.MessageRequest)
+               }
+
+               if err := stream.Send(out); err != nil {
+                       return err
+               }
+       }
+}
+
+var reflectionServe *ReflectionServer
+
+func init() {
+       reflectionServe = NewServer()
+       server.SetProServices(&server.ServiceDefinition{
+               Handler: reflectionServe,
+               Info:    &rpb.ServerReflection_ServiceInfo,
+               Opts:    []server.ServiceOption{server.WithNotRegister()},
+       })
+}
+
+func Register(s ServiceInfoProvider) {
+       reflectionServe.s = s
+}
diff --git a/protocol/triple/reflection/triple_reflection/reflection.pb.go 
b/protocol/triple/reflection/triple_reflection/reflection.pb.go
new file mode 100644
index 000000000..2e66e7108
--- /dev/null
+++ b/protocol/triple/reflection/triple_reflection/reflection.pb.go
@@ -0,0 +1,956 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+// Service exported by server reflection
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+//     protoc-gen-go v1.29.0
+//     protoc        v3.15.5
+// source: reflection.proto
+
+package triple_reflection
+
+import (
+       reflect "reflect"
+       sync "sync"
+)
+
+import (
+       protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+
+       protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+)
+
+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)
+)
+
+// The message sent by the client when calling ServerReflectionInfo method.
+type ServerReflectionRequest struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Host string `protobuf:"bytes,1,opt,name=host,proto3" 
json:"host,omitempty"`
+       // To use reflection service, the client should set one of the following
+       // fields in message_request. The server distinguishes requests by their
+       // defined field and then handles them using corresponding methods.
+       //
+       // Types that are assignable to MessageRequest:
+       //
+       //      *ServerReflectionRequest_FileByFilename
+       //      *ServerReflectionRequest_FileContainingSymbol
+       //      *ServerReflectionRequest_FileContainingExtension
+       //      *ServerReflectionRequest_AllExtensionNumbersOfType
+       //      *ServerReflectionRequest_ListServices
+       MessageRequest isServerReflectionRequest_MessageRequest 
`protobuf_oneof:"message_request"`
+}
+
+func (x *ServerReflectionRequest) Reset() {
+       *x = ServerReflectionRequest{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_reflection_proto_msgTypes[0]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *ServerReflectionRequest) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ServerReflectionRequest) ProtoMessage() {}
+
+func (x *ServerReflectionRequest) ProtoReflect() protoreflect.Message {
+       mi := &file_reflection_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 ServerReflectionRequest.ProtoReflect.Descriptor instead.
+func (*ServerReflectionRequest) Descriptor() ([]byte, []int) {
+       return file_reflection_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *ServerReflectionRequest) GetHost() string {
+       if x != nil {
+               return x.Host
+       }
+       return ""
+}
+
+func (m *ServerReflectionRequest) GetMessageRequest() 
isServerReflectionRequest_MessageRequest {
+       if m != nil {
+               return m.MessageRequest
+       }
+       return nil
+}
+
+func (x *ServerReflectionRequest) GetFileByFilename() string {
+       if x, ok := 
x.GetMessageRequest().(*ServerReflectionRequest_FileByFilename); ok {
+               return x.FileByFilename
+       }
+       return ""
+}
+
+func (x *ServerReflectionRequest) GetFileContainingSymbol() string {
+       if x, ok := 
x.GetMessageRequest().(*ServerReflectionRequest_FileContainingSymbol); ok {
+               return x.FileContainingSymbol
+       }
+       return ""
+}
+
+func (x *ServerReflectionRequest) GetFileContainingExtension() 
*ExtensionRequest {
+       if x, ok := 
x.GetMessageRequest().(*ServerReflectionRequest_FileContainingExtension); ok {
+               return x.FileContainingExtension
+       }
+       return nil
+}
+
+func (x *ServerReflectionRequest) GetAllExtensionNumbersOfType() string {
+       if x, ok := 
x.GetMessageRequest().(*ServerReflectionRequest_AllExtensionNumbersOfType); ok {
+               return x.AllExtensionNumbersOfType
+       }
+       return ""
+}
+
+func (x *ServerReflectionRequest) GetListServices() string {
+       if x, ok := 
x.GetMessageRequest().(*ServerReflectionRequest_ListServices); ok {
+               return x.ListServices
+       }
+       return ""
+}
+
+type isServerReflectionRequest_MessageRequest interface {
+       isServerReflectionRequest_MessageRequest()
+}
+
+type ServerReflectionRequest_FileByFilename struct {
+       // Find a proto file by the file name.
+       FileByFilename string 
`protobuf:"bytes,3,opt,name=file_by_filename,json=fileByFilename,proto3,oneof"`
+}
+
+type ServerReflectionRequest_FileContainingSymbol struct {
+       // Find the proto file that declares the given fully-qualified symbol 
name.
+       // This field should be a fully-qualified symbol name
+       // (e.g. <package>.<service>[.<method>] or <package>.<type>).
+       FileContainingSymbol string 
`protobuf:"bytes,4,opt,name=file_containing_symbol,json=fileContainingSymbol,proto3,oneof"`
+}
+
+type ServerReflectionRequest_FileContainingExtension struct {
+       // Find the proto file which defines an extension extending the given
+       // message type with the given field number.
+       FileContainingExtension *ExtensionRequest 
`protobuf:"bytes,5,opt,name=file_containing_extension,json=fileContainingExtension,proto3,oneof"`
+}
+
+type ServerReflectionRequest_AllExtensionNumbersOfType struct {
+       // Finds the tag numbers used by all known extensions of extendee_type, 
and
+       // appends them to ExtensionNumberResponse in an undefined order.
+       // Its corresponding method is best-effort: it's not guaranteed that the
+       // reflection service will implement this method, and it's not 
guaranteed
+       // that this method will provide all extensions. Returns
+       // StatusCode::UNIMPLEMENTED if it's not implemented.
+       // This field should be a fully-qualified type name. The format is
+       // <package>.<type>
+       AllExtensionNumbersOfType string 
`protobuf:"bytes,6,opt,name=all_extension_numbers_of_type,json=allExtensionNumbersOfType,proto3,oneof"`
+}
+
+type ServerReflectionRequest_ListServices struct {
+       // List the full names of registered services. The content will not be
+       // checked.
+       ListServices string 
`protobuf:"bytes,7,opt,name=list_services,json=listServices,proto3,oneof"`
+}
+
+func (*ServerReflectionRequest_FileByFilename) 
isServerReflectionRequest_MessageRequest() {}
+
+func (*ServerReflectionRequest_FileContainingSymbol) 
isServerReflectionRequest_MessageRequest() {}
+
+func (*ServerReflectionRequest_FileContainingExtension) 
isServerReflectionRequest_MessageRequest() {}
+
+func (*ServerReflectionRequest_AllExtensionNumbersOfType) 
isServerReflectionRequest_MessageRequest() {
+}
+
+func (*ServerReflectionRequest_ListServices) 
isServerReflectionRequest_MessageRequest() {}
+
+// The type name and extension number sent by the client when requesting
+// file_containing_extension.
+type ExtensionRequest struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       // Fully-qualified type name. The format should be <package>.<type>
+       ContainingType  string 
`protobuf:"bytes,1,opt,name=containing_type,json=containingType,proto3" 
json:"containing_type,omitempty"`
+       ExtensionNumber int32  
`protobuf:"varint,2,opt,name=extension_number,json=extensionNumber,proto3" 
json:"extension_number,omitempty"`
+}
+
+func (x *ExtensionRequest) Reset() {
+       *x = ExtensionRequest{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_reflection_proto_msgTypes[1]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *ExtensionRequest) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ExtensionRequest) ProtoMessage() {}
+
+func (x *ExtensionRequest) ProtoReflect() protoreflect.Message {
+       mi := &file_reflection_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 ExtensionRequest.ProtoReflect.Descriptor instead.
+func (*ExtensionRequest) Descriptor() ([]byte, []int) {
+       return file_reflection_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *ExtensionRequest) GetContainingType() string {
+       if x != nil {
+               return x.ContainingType
+       }
+       return ""
+}
+
+func (x *ExtensionRequest) GetExtensionNumber() int32 {
+       if x != nil {
+               return x.ExtensionNumber
+       }
+       return 0
+}
+
+// The message sent by the server to answer ServerReflectionInfo method.
+type ServerReflectionResponse struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       ValidHost       string                   
`protobuf:"bytes,1,opt,name=valid_host,json=validHost,proto3" 
json:"valid_host,omitempty"`
+       OriginalRequest *ServerReflectionRequest 
`protobuf:"bytes,2,opt,name=original_request,json=originalRequest,proto3" 
json:"original_request,omitempty"`
+       // The server sets one of the following fields according to the
+       // message_request in the request.
+       //
+       // Types that are assignable to MessageResponse:
+       //
+       //      *ServerReflectionResponse_FileDescriptorResponse
+       //      *ServerReflectionResponse_AllExtensionNumbersResponse
+       //      *ServerReflectionResponse_ListServicesResponse
+       //      *ServerReflectionResponse_ErrorResponse
+       MessageResponse isServerReflectionResponse_MessageResponse 
`protobuf_oneof:"message_response"`
+}
+
+func (x *ServerReflectionResponse) Reset() {
+       *x = ServerReflectionResponse{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_reflection_proto_msgTypes[2]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *ServerReflectionResponse) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ServerReflectionResponse) ProtoMessage() {}
+
+func (x *ServerReflectionResponse) ProtoReflect() protoreflect.Message {
+       mi := &file_reflection_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 ServerReflectionResponse.ProtoReflect.Descriptor instead.
+func (*ServerReflectionResponse) Descriptor() ([]byte, []int) {
+       return file_reflection_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *ServerReflectionResponse) GetValidHost() string {
+       if x != nil {
+               return x.ValidHost
+       }
+       return ""
+}
+
+func (x *ServerReflectionResponse) GetOriginalRequest() 
*ServerReflectionRequest {
+       if x != nil {
+               return x.OriginalRequest
+       }
+       return nil
+}
+
+func (m *ServerReflectionResponse) GetMessageResponse() 
isServerReflectionResponse_MessageResponse {
+       if m != nil {
+               return m.MessageResponse
+       }
+       return nil
+}
+
+func (x *ServerReflectionResponse) GetFileDescriptorResponse() 
*FileDescriptorResponse {
+       if x, ok := 
x.GetMessageResponse().(*ServerReflectionResponse_FileDescriptorResponse); ok {
+               return x.FileDescriptorResponse
+       }
+       return nil
+}
+
+func (x *ServerReflectionResponse) GetAllExtensionNumbersResponse() 
*ExtensionNumberResponse {
+       if x, ok := 
x.GetMessageResponse().(*ServerReflectionResponse_AllExtensionNumbersResponse); 
ok {
+               return x.AllExtensionNumbersResponse
+       }
+       return nil
+}
+
+func (x *ServerReflectionResponse) GetListServicesResponse() 
*ListServiceResponse {
+       if x, ok := 
x.GetMessageResponse().(*ServerReflectionResponse_ListServicesResponse); ok {
+               return x.ListServicesResponse
+       }
+       return nil
+}
+
+func (x *ServerReflectionResponse) GetErrorResponse() *ErrorResponse {
+       if x, ok := 
x.GetMessageResponse().(*ServerReflectionResponse_ErrorResponse); ok {
+               return x.ErrorResponse
+       }
+       return nil
+}
+
+type isServerReflectionResponse_MessageResponse interface {
+       isServerReflectionResponse_MessageResponse()
+}
+
+type ServerReflectionResponse_FileDescriptorResponse struct {
+       // This message is used to answer file_by_filename, 
file_containing_symbol,
+       // file_containing_extension requests with transitive dependencies.
+       // As the repeated label is not allowed in oneof fields, we use a
+       // FileDescriptorResponse message to encapsulate the repeated fields.
+       // The reflection service is allowed to avoid sending 
FileDescriptorProtos
+       // that were previously sent in response to earlier requests in the 
stream.
+       FileDescriptorResponse *FileDescriptorResponse 
`protobuf:"bytes,4,opt,name=file_descriptor_response,json=fileDescriptorResponse,proto3,oneof"`
+}
+
+type ServerReflectionResponse_AllExtensionNumbersResponse struct {
+       // This message is used to answer all_extension_numbers_of_type 
requests.
+       AllExtensionNumbersResponse *ExtensionNumberResponse 
`protobuf:"bytes,5,opt,name=all_extension_numbers_response,json=allExtensionNumbersResponse,proto3,oneof"`
+}
+
+type ServerReflectionResponse_ListServicesResponse struct {
+       // This message is used to answer list_services requests.
+       ListServicesResponse *ListServiceResponse 
`protobuf:"bytes,6,opt,name=list_services_response,json=listServicesResponse,proto3,oneof"`
+}
+
+type ServerReflectionResponse_ErrorResponse struct {
+       // This message is used when an error occurs.
+       ErrorResponse *ErrorResponse 
`protobuf:"bytes,7,opt,name=error_response,json=errorResponse,proto3,oneof"`
+}
+
+func (*ServerReflectionResponse_FileDescriptorResponse) 
isServerReflectionResponse_MessageResponse() {
+}
+
+func (*ServerReflectionResponse_AllExtensionNumbersResponse) 
isServerReflectionResponse_MessageResponse() {
+}
+
+func (*ServerReflectionResponse_ListServicesResponse) 
isServerReflectionResponse_MessageResponse() {}
+
+func (*ServerReflectionResponse_ErrorResponse) 
isServerReflectionResponse_MessageResponse() {}
+
+// Serialized FileDescriptorProto messages sent by the server answering
+// a file_by_filename, file_containing_symbol, or file_containing_extension
+// request.
+type FileDescriptorResponse struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       // Serialized FileDescriptorProto messages. We avoid taking a 
dependency on
+       // descriptor.proto, which uses proto2 only features, by making them 
opaque
+       // bytes instead.
+       FileDescriptorProto [][]byte 
`protobuf:"bytes,1,rep,name=file_descriptor_proto,json=fileDescriptorProto,proto3"
 json:"file_descriptor_proto,omitempty"`
+}
+
+func (x *FileDescriptorResponse) Reset() {
+       *x = FileDescriptorResponse{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_reflection_proto_msgTypes[3]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *FileDescriptorResponse) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FileDescriptorResponse) ProtoMessage() {}
+
+func (x *FileDescriptorResponse) ProtoReflect() protoreflect.Message {
+       mi := &file_reflection_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 FileDescriptorResponse.ProtoReflect.Descriptor instead.
+func (*FileDescriptorResponse) Descriptor() ([]byte, []int) {
+       return file_reflection_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *FileDescriptorResponse) GetFileDescriptorProto() [][]byte {
+       if x != nil {
+               return x.FileDescriptorProto
+       }
+       return nil
+}
+
+// A list of extension numbers sent by the server answering
+// all_extension_numbers_of_type request.
+type ExtensionNumberResponse struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       // Full name of the base type, including the package name. The format
+       // is <package>.<type>
+       BaseTypeName    string  
`protobuf:"bytes,1,opt,name=base_type_name,json=baseTypeName,proto3" 
json:"base_type_name,omitempty"`
+       ExtensionNumber []int32 
`protobuf:"varint,2,rep,packed,name=extension_number,json=extensionNumber,proto3"
 json:"extension_number,omitempty"`
+}
+
+func (x *ExtensionNumberResponse) Reset() {
+       *x = ExtensionNumberResponse{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_reflection_proto_msgTypes[4]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *ExtensionNumberResponse) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ExtensionNumberResponse) ProtoMessage() {}
+
+func (x *ExtensionNumberResponse) ProtoReflect() protoreflect.Message {
+       mi := &file_reflection_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 ExtensionNumberResponse.ProtoReflect.Descriptor instead.
+func (*ExtensionNumberResponse) Descriptor() ([]byte, []int) {
+       return file_reflection_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *ExtensionNumberResponse) GetBaseTypeName() string {
+       if x != nil {
+               return x.BaseTypeName
+       }
+       return ""
+}
+
+func (x *ExtensionNumberResponse) GetExtensionNumber() []int32 {
+       if x != nil {
+               return x.ExtensionNumber
+       }
+       return nil
+}
+
+// A list of ServiceResponse sent by the server answering list_services 
request.
+type ListServiceResponse struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       // The information of each service may be expanded in the future, so we 
use
+       // ServiceResponse message to encapsulate it.
+       Service []*ServiceResponse `protobuf:"bytes,1,rep,name=service,proto3" 
json:"service,omitempty"`
+}
+
+func (x *ListServiceResponse) Reset() {
+       *x = ListServiceResponse{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_reflection_proto_msgTypes[5]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *ListServiceResponse) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ListServiceResponse) ProtoMessage() {}
+
+func (x *ListServiceResponse) ProtoReflect() protoreflect.Message {
+       mi := &file_reflection_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 ListServiceResponse.ProtoReflect.Descriptor instead.
+func (*ListServiceResponse) Descriptor() ([]byte, []int) {
+       return file_reflection_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *ListServiceResponse) GetService() []*ServiceResponse {
+       if x != nil {
+               return x.Service
+       }
+       return nil
+}
+
+// The information of a single service used by ListServiceResponse to answer
+// list_services request.
+type ServiceResponse struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       // Full name of a registered service, including its package name. The 
format
+       // is <package>.<service>
+       Name string `protobuf:"bytes,1,opt,name=name,proto3" 
json:"name,omitempty"`
+}
+
+func (x *ServiceResponse) Reset() {
+       *x = ServiceResponse{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_reflection_proto_msgTypes[6]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *ServiceResponse) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ServiceResponse) ProtoMessage() {}
+
+func (x *ServiceResponse) ProtoReflect() protoreflect.Message {
+       mi := &file_reflection_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 ServiceResponse.ProtoReflect.Descriptor instead.
+func (*ServiceResponse) Descriptor() ([]byte, []int) {
+       return file_reflection_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *ServiceResponse) GetName() string {
+       if x != nil {
+               return x.Name
+       }
+       return ""
+}
+
+// The error code and error message sent by the server when an error occurs.
+type ErrorResponse struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       // This field uses the error codes defined in grpc::StatusCode.
+       ErrorCode    int32  
`protobuf:"varint,1,opt,name=error_code,json=errorCode,proto3" 
json:"error_code,omitempty"`
+       ErrorMessage string 
`protobuf:"bytes,2,opt,name=error_message,json=errorMessage,proto3" 
json:"error_message,omitempty"`
+}
+
+func (x *ErrorResponse) Reset() {
+       *x = ErrorResponse{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_reflection_proto_msgTypes[7]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *ErrorResponse) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ErrorResponse) ProtoMessage() {}
+
+func (x *ErrorResponse) ProtoReflect() protoreflect.Message {
+       mi := &file_reflection_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 ErrorResponse.ProtoReflect.Descriptor instead.
+func (*ErrorResponse) Descriptor() ([]byte, []int) {
+       return file_reflection_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *ErrorResponse) GetErrorCode() int32 {
+       if x != nil {
+               return x.ErrorCode
+       }
+       return 0
+}
+
+func (x *ErrorResponse) GetErrorMessage() string {
+       if x != nil {
+               return x.ErrorMessage
+       }
+       return ""
+}
+
+var File_reflection_proto protoreflect.FileDescriptor
+
+var file_reflection_proto_rawDesc = []byte{
+       0x0a, 0x10, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 
0x2e, 0x70, 0x72, 0x6f,
+       0x74, 0x6f, 0x12, 0x18, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2e, 0x72, 0x65, 
0x66, 0x6c, 0x65, 0x63,
+       0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 
0x22, 0xf9, 0x02, 0x0a,
+       0x17, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 
0x63, 0x74, 0x69, 0x6f,
+       0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 
0x68, 0x6f, 0x73, 0x74,
+       0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 
0x12, 0x2a, 0x0a, 0x10,
+       0x66, 0x69, 0x6c, 0x65, 0x5f, 0x62, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x65, 
0x6e, 0x61, 0x6d, 0x65,
+       0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0e, 0x66, 0x69, 
0x6c, 0x65, 0x42, 0x79,
+       0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x16, 
0x66, 0x69, 0x6c, 0x65,
+       0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 
0x73, 0x79, 0x6d, 0x62,
+       0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x14, 
0x66, 0x69, 0x6c, 0x65,
+       0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x79, 
0x6d, 0x62, 0x6f, 0x6c,
+       0x12, 0x68, 0x0a, 0x19, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 
0x74, 0x61, 0x69, 0x6e,
+       0x69, 0x6e, 0x67, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 
0x6e, 0x18, 0x05, 0x20,
+       0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2e, 
0x72, 0x65, 0x66, 0x6c,
+       0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 
0x68, 0x61, 0x2e, 0x45,
+       0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 
0x65, 0x73, 0x74, 0x48,
+       0x00, 0x52, 0x17, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 
0x69, 0x6e, 0x69, 0x6e,
+       0x67, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x42, 
0x0a, 0x1d, 0x61, 0x6c,
+       0x6c, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 
0x6e, 0x75, 0x6d, 0x62,
+       0x65, 0x72, 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 
0x06, 0x20, 0x01, 0x28,
+       0x09, 0x48, 0x00, 0x52, 0x19, 0x61, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 
0x6e, 0x73, 0x69, 0x6f,
+       0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x4f, 0x66, 0x54, 0x79, 
0x70, 0x65, 0x12, 0x25,
+       0x0a, 0x0d, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 
0x63, 0x65, 0x73, 0x18,
+       0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x6c, 0x69, 0x73, 
0x74, 0x53, 0x65, 0x72,
+       0x76, 0x69, 0x63, 0x65, 0x73, 0x42, 0x11, 0x0a, 0x0f, 0x6d, 0x65, 0x73, 
0x73, 0x61, 0x67, 0x65,
+       0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x66, 0x0a, 0x10, 
0x45, 0x78, 0x74, 0x65,
+       0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 
0x12, 0x27, 0x0a, 0x0f,
+       0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x74, 
0x79, 0x70, 0x65, 0x18,
+       0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 
0x69, 0x6e, 0x69, 0x6e,
+       0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x78, 0x74, 
0x65, 0x6e, 0x73, 0x69,
+       0x6f, 0x6e, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 
0x01, 0x28, 0x05, 0x52,
+       0x0f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 
0x6d, 0x62, 0x65, 0x72,
+       0x22, 0xcc, 0x04, 0x0a, 0x18, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 
0x65, 0x66, 0x6c, 0x65,
+       0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 
0x65, 0x12, 0x1d, 0x0a,
+       0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 
0x01, 0x20, 0x01, 0x28,
+       0x09, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x48, 0x6f, 0x73, 0x74, 
0x12, 0x5c, 0x0a, 0x10,
+       0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x71, 
0x75, 0x65, 0x73, 0x74,
+       0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x64, 0x75, 0x62, 
0x62, 0x6f, 0x2e, 0x72,
+       0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 
0x61, 0x6c, 0x70, 0x68,
+       0x61, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, 
0x65, 0x63, 0x74, 0x69,
+       0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0f, 0x6f, 
0x72, 0x69, 0x67, 0x69,
+       0x6e, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x6c, 
0x0a, 0x18, 0x66, 0x69,
+       0x6c, 0x65, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 
0x72, 0x5f, 0x72, 0x65,
+       0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 
0x32, 0x30, 0x2e, 0x64,
+       0x75, 0x62, 0x62, 0x6f, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 
0x69, 0x6f, 0x6e, 0x2e,
+       0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x46, 0x69, 0x6c, 0x65, 
0x44, 0x65, 0x73, 0x63,
+       0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 
0x73, 0x65, 0x48, 0x00,
+       0x52, 0x16, 0x66, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 
0x70, 0x74, 0x6f, 0x72,
+       0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, 0x1e, 
0x61, 0x6c, 0x6c, 0x5f,
+       0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x75, 
0x6d, 0x62, 0x65, 0x72,
+       0x73, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x05, 
0x20, 0x01, 0x28, 0x0b,
+       0x32, 0x31, 0x2e, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2e, 0x72, 0x65, 0x66, 
0x6c, 0x65, 0x63, 0x74,
+       0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 
0x45, 0x78, 0x74, 0x65,
+       0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 
0x65, 0x73, 0x70, 0x6f,
+       0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x1b, 0x61, 0x6c, 0x6c, 0x45, 0x78, 
0x74, 0x65, 0x6e, 0x73,
+       0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 
0x73, 0x70, 0x6f, 0x6e,
+       0x73, 0x65, 0x12, 0x65, 0x0a, 0x16, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x73, 
0x65, 0x72, 0x76, 0x69,
+       0x63, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 
0x18, 0x06, 0x20, 0x01,
+       0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2e, 0x72, 
0x65, 0x66, 0x6c, 0x65,
+       0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 
0x61, 0x2e, 0x4c, 0x69,
+       0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 
0x70, 0x6f, 0x6e, 0x73,
+       0x65, 0x48, 0x00, 0x52, 0x14, 0x6c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 
0x76, 0x69, 0x63, 0x65,
+       0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 
0x0e, 0x65, 0x72, 0x72,
+       0x6f, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 
0x07, 0x20, 0x01, 0x28,
+       0x0b, 0x32, 0x27, 0x2e, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2e, 0x72, 0x65, 
0x66, 0x6c, 0x65, 0x63,
+       0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 
0x2e, 0x45, 0x72, 0x72,
+       0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 
0x52, 0x0d, 0x65, 0x72,
+       0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 
0x12, 0x0a, 0x10, 0x6d,
+       0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 
0x6e, 0x73, 0x65, 0x22,
+       0x4c, 0x0a, 0x16, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 
0x69, 0x70, 0x74, 0x6f,
+       0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 
0x15, 0x66, 0x69, 0x6c,
+       0x65, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 
0x5f, 0x70, 0x72, 0x6f,
+       0x74, 0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x13, 0x66, 0x69, 
0x6c, 0x65, 0x44, 0x65,
+       0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 
0x6f, 0x22, 0x6a, 0x0a,
+       0x17, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 
0x6d, 0x62, 0x65, 0x72,
+       0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x0e, 
0x62, 0x61, 0x73, 0x65,
+       0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 
0x20, 0x01, 0x28, 0x09,
+       0x52, 0x0c, 0x62, 0x61, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x4e, 0x61, 
0x6d, 0x65, 0x12, 0x29,
+       0x0a, 0x10, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 
0x6e, 0x75, 0x6d, 0x62,
+       0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0f, 0x65, 0x78, 
0x74, 0x65, 0x6e, 0x73,
+       0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x5a, 0x0a, 
0x13, 0x4c, 0x69, 0x73,
+       0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 
0x6f, 0x6e, 0x73, 0x65,
+       0x12, 0x43, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 
0x01, 0x20, 0x03, 0x28,
+       0x0b, 0x32, 0x29, 0x2e, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2e, 0x72, 0x65, 
0x66, 0x6c, 0x65, 0x63,
+       0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 
0x2e, 0x53, 0x65, 0x72,
+       0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 
0x52, 0x07, 0x73, 0x65,
+       0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x25, 0x0a, 0x0f, 0x53, 0x65, 0x72, 
0x76, 0x69, 0x63, 0x65,
+       0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 
0x6e, 0x61, 0x6d, 0x65,
+       0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 
0x22, 0x53, 0x0a, 0x0d,
+       0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 
0x65, 0x12, 0x1d, 0x0a,
+       0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 
0x01, 0x20, 0x01, 0x28,
+       0x05, 0x52, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 
0x12, 0x23, 0x0a, 0x0d,
+       0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 
0x65, 0x18, 0x02, 0x20,
+       0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 
0x73, 0x73, 0x61, 0x67,
+       0x65, 0x32, 0x96, 0x01, 0x0a, 0x10, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 
0x52, 0x65, 0x66, 0x6c,
+       0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x81, 0x01, 0x0a, 0x14, 0x53, 
0x65, 0x72, 0x76, 0x65,
+       0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 
0x6e, 0x66, 0x6f, 0x12,
+       0x31, 0x2e, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2e, 0x72, 0x65, 0x66, 0x6c, 
0x65, 0x63, 0x74, 0x69,
+       0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 
0x65, 0x72, 0x76, 0x65,
+       0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 
0x65, 0x71, 0x75, 0x65,
+       0x73, 0x74, 0x1a, 0x32, 0x2e, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2e, 0x72, 
0x65, 0x66, 0x6c, 0x65,
+       0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 
0x61, 0x2e, 0x53, 0x65,
+       0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 
0x6f, 0x6e, 0x52, 0x65,
+       0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x4b, 
0x5a, 0x49, 0x64, 0x75,
+       0x62, 0x62, 0x6f, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x6f, 
0x72, 0x67, 0x2f, 0x64,
+       0x75, 0x62, 0x62, 0x6f, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x70, 
0x72, 0x6f, 0x74, 0x6f,
+       0x63, 0x6f, 0x6c, 0x2f, 0x74, 0x72, 0x69, 0x70, 0x6c, 0x65, 0x2f, 0x72, 
0x65, 0x66, 0x6c, 0x65,
+       0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x72, 0x69, 0x70, 0x6c, 0x65, 
0x5f, 0x72, 0x65, 0x66,
+       0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 
0x74, 0x6f, 0x33,
+}
+
+var (
+       file_reflection_proto_rawDescOnce sync.Once
+       file_reflection_proto_rawDescData = file_reflection_proto_rawDesc
+)
+
+func file_reflection_proto_rawDescGZIP() []byte {
+       file_reflection_proto_rawDescOnce.Do(func() {
+               file_reflection_proto_rawDescData = 
protoimpl.X.CompressGZIP(file_reflection_proto_rawDescData)
+       })
+       return file_reflection_proto_rawDescData
+}
+
+var file_reflection_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
+var file_reflection_proto_goTypes = []interface{}{
+       (*ServerReflectionRequest)(nil),  // 0: 
dubbo.reflection.v1alpha.ServerReflectionRequest
+       (*ExtensionRequest)(nil),         // 1: 
dubbo.reflection.v1alpha.ExtensionRequest
+       (*ServerReflectionResponse)(nil), // 2: 
dubbo.reflection.v1alpha.ServerReflectionResponse
+       (*FileDescriptorResponse)(nil),   // 3: 
dubbo.reflection.v1alpha.FileDescriptorResponse
+       (*ExtensionNumberResponse)(nil),  // 4: 
dubbo.reflection.v1alpha.ExtensionNumberResponse
+       (*ListServiceResponse)(nil),      // 5: 
dubbo.reflection.v1alpha.ListServiceResponse
+       (*ServiceResponse)(nil),          // 6: 
dubbo.reflection.v1alpha.ServiceResponse
+       (*ErrorResponse)(nil),            // 7: 
dubbo.reflection.v1alpha.ErrorResponse
+}
+var file_reflection_proto_depIdxs = []int32{
+       1, // 0: 
dubbo.reflection.v1alpha.ServerReflectionRequest.file_containing_extension:type_name
 -> dubbo.reflection.v1alpha.ExtensionRequest
+       0, // 1: 
dubbo.reflection.v1alpha.ServerReflectionResponse.original_request:type_name -> 
dubbo.reflection.v1alpha.ServerReflectionRequest
+       3, // 2: 
dubbo.reflection.v1alpha.ServerReflectionResponse.file_descriptor_response:type_name
 -> dubbo.reflection.v1alpha.FileDescriptorResponse
+       4, // 3: 
dubbo.reflection.v1alpha.ServerReflectionResponse.all_extension_numbers_response:type_name
 -> dubbo.reflection.v1alpha.ExtensionNumberResponse
+       5, // 4: 
dubbo.reflection.v1alpha.ServerReflectionResponse.list_services_response:type_name
 -> dubbo.reflection.v1alpha.ListServiceResponse
+       7, // 5: 
dubbo.reflection.v1alpha.ServerReflectionResponse.error_response:type_name -> 
dubbo.reflection.v1alpha.ErrorResponse
+       6, // 6: dubbo.reflection.v1alpha.ListServiceResponse.service:type_name 
-> dubbo.reflection.v1alpha.ServiceResponse
+       0, // 7: 
dubbo.reflection.v1alpha.ServerReflection.ServerReflectionInfo:input_type -> 
dubbo.reflection.v1alpha.ServerReflectionRequest
+       2, // 8: 
dubbo.reflection.v1alpha.ServerReflection.ServerReflectionInfo:output_type -> 
dubbo.reflection.v1alpha.ServerReflectionResponse
+       8, // [8:9] is the sub-list for method output_type
+       7, // [7:8] is the sub-list for method input_type
+       7, // [7:7] is the sub-list for extension type_name
+       7, // [7:7] is the sub-list for extension extendee
+       0, // [0:7] is the sub-list for field type_name
+}
+
+func init() { file_reflection_proto_init() }
+func file_reflection_proto_init() {
+       if File_reflection_proto != nil {
+               return
+       }
+       if !protoimpl.UnsafeEnabled {
+               file_reflection_proto_msgTypes[0].Exporter = func(v 
interface{}, i int) interface{} {
+                       switch v := v.(*ServerReflectionRequest); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_reflection_proto_msgTypes[1].Exporter = func(v 
interface{}, i int) interface{} {
+                       switch v := v.(*ExtensionRequest); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_reflection_proto_msgTypes[2].Exporter = func(v 
interface{}, i int) interface{} {
+                       switch v := v.(*ServerReflectionResponse); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_reflection_proto_msgTypes[3].Exporter = func(v 
interface{}, i int) interface{} {
+                       switch v := v.(*FileDescriptorResponse); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_reflection_proto_msgTypes[4].Exporter = func(v 
interface{}, i int) interface{} {
+                       switch v := v.(*ExtensionNumberResponse); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_reflection_proto_msgTypes[5].Exporter = func(v 
interface{}, i int) interface{} {
+                       switch v := v.(*ListServiceResponse); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_reflection_proto_msgTypes[6].Exporter = func(v 
interface{}, i int) interface{} {
+                       switch v := v.(*ServiceResponse); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_reflection_proto_msgTypes[7].Exporter = func(v 
interface{}, i int) interface{} {
+                       switch v := v.(*ErrorResponse); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+       }
+       file_reflection_proto_msgTypes[0].OneofWrappers = []interface{}{
+               (*ServerReflectionRequest_FileByFilename)(nil),
+               (*ServerReflectionRequest_FileContainingSymbol)(nil),
+               (*ServerReflectionRequest_FileContainingExtension)(nil),
+               (*ServerReflectionRequest_AllExtensionNumbersOfType)(nil),
+               (*ServerReflectionRequest_ListServices)(nil),
+       }
+       file_reflection_proto_msgTypes[2].OneofWrappers = []interface{}{
+               (*ServerReflectionResponse_FileDescriptorResponse)(nil),
+               (*ServerReflectionResponse_AllExtensionNumbersResponse)(nil),
+               (*ServerReflectionResponse_ListServicesResponse)(nil),
+               (*ServerReflectionResponse_ErrorResponse)(nil),
+       }
+       type x struct{}
+       out := protoimpl.TypeBuilder{
+               File: protoimpl.DescBuilder{
+                       GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+                       RawDescriptor: file_reflection_proto_rawDesc,
+                       NumEnums:      0,
+                       NumMessages:   8,
+                       NumExtensions: 0,
+                       NumServices:   1,
+               },
+               GoTypes:           file_reflection_proto_goTypes,
+               DependencyIndexes: file_reflection_proto_depIdxs,
+               MessageInfos:      file_reflection_proto_msgTypes,
+       }.Build()
+       File_reflection_proto = out.File
+       file_reflection_proto_rawDesc = nil
+       file_reflection_proto_goTypes = nil
+       file_reflection_proto_depIdxs = nil
+}
diff --git a/protocol/triple/reflection/triple_reflection/reflection.proto 
b/protocol/triple/reflection/triple_reflection/reflection.proto
new file mode 100644
index 000000000..db96af2ab
--- /dev/null
+++ b/protocol/triple/reflection/triple_reflection/reflection.proto
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+// Service exported by server reflection
+
+syntax = "proto3";
+
+package dubbo.reflection.v1alpha;
+
+option go_package = 
"dubbo.apache.org/dubbo-go/v3/protocol/triple/reflection/triple_reflection";
+
+service ServerReflection {
+  // The reflection service is structured as a bidirectional stream, ensuring
+  // all related requests go to a single server.
+  rpc ServerReflectionInfo(stream ServerReflectionRequest)
+      returns (stream ServerReflectionResponse);
+}
+
+// The message sent by the client when calling ServerReflectionInfo method.
+message ServerReflectionRequest {
+  string host = 1;
+  // To use reflection service, the client should set one of the following
+  // fields in message_request. The server distinguishes requests by their
+  // defined field and then handles them using corresponding methods.
+  oneof message_request {
+    // Find a proto file by the file name.
+    string file_by_filename = 3;
+
+    // Find the proto file that declares the given fully-qualified symbol name.
+    // This field should be a fully-qualified symbol name
+    // (e.g. <package>.<service>[.<method>] or <package>.<type>).
+    string file_containing_symbol = 4;
+
+    // Find the proto file which defines an extension extending the given
+    // message type with the given field number.
+    ExtensionRequest file_containing_extension = 5;
+
+    // Finds the tag numbers used by all known extensions of extendee_type, and
+    // appends them to ExtensionNumberResponse in an undefined order.
+    // Its corresponding method is best-effort: it's not guaranteed that the
+    // reflection service will implement this method, and it's not guaranteed
+    // that this method will provide all extensions. Returns
+    // StatusCode::UNIMPLEMENTED if it's not implemented.
+    // This field should be a fully-qualified type name. The format is
+    // <package>.<type>
+    string all_extension_numbers_of_type = 6;
+
+    // List the full names of registered services. The content will not be
+    // checked.
+    string list_services = 7;
+  }
+}
+
+// The type name and extension number sent by the client when requesting
+// file_containing_extension.
+message ExtensionRequest {
+  // Fully-qualified type name. The format should be <package>.<type>
+  string containing_type = 1;
+  int32 extension_number = 2;
+}
+
+// The message sent by the server to answer ServerReflectionInfo method.
+message ServerReflectionResponse {
+  string valid_host = 1;
+  ServerReflectionRequest original_request = 2;
+  // The server sets one of the following fields according to the
+  // message_request in the request.
+  oneof message_response {
+    // This message is used to answer file_by_filename, file_containing_symbol,
+    // file_containing_extension requests with transitive dependencies.
+    // As the repeated label is not allowed in oneof fields, we use a
+    // FileDescriptorResponse message to encapsulate the repeated fields.
+    // The reflection service is allowed to avoid sending FileDescriptorProtos
+    // that were previously sent in response to earlier requests in the stream.
+    FileDescriptorResponse file_descriptor_response = 4;
+
+    // This message is used to answer all_extension_numbers_of_type requests.
+    ExtensionNumberResponse all_extension_numbers_response = 5;
+
+    // This message is used to answer list_services requests.
+    ListServiceResponse list_services_response = 6;
+
+    // This message is used when an error occurs.
+    ErrorResponse error_response = 7;
+  }
+}
+
+// Serialized FileDescriptorProto messages sent by the server answering
+// a file_by_filename, file_containing_symbol, or file_containing_extension
+// request.
+message FileDescriptorResponse {
+  // Serialized FileDescriptorProto messages. We avoid taking a dependency on
+  // descriptor.proto, which uses proto2 only features, by making them opaque
+  // bytes instead.
+  repeated bytes file_descriptor_proto = 1;
+}
+
+// A list of extension numbers sent by the server answering
+// all_extension_numbers_of_type request.
+message ExtensionNumberResponse {
+  // Full name of the base type, including the package name. The format
+  // is <package>.<type>
+  string base_type_name = 1;
+  repeated int32 extension_number = 2;
+}
+
+// A list of ServiceResponse sent by the server answering list_services 
request.
+message ListServiceResponse {
+  // The information of each service may be expanded in the future, so we use
+  // ServiceResponse message to encapsulate it.
+  repeated ServiceResponse service = 1;
+}
+
+// The information of a single service used by ListServiceResponse to answer
+// list_services request.
+message ServiceResponse {
+  // Full name of a registered service, including its package name. The format
+  // is <package>.<service>
+  string name = 1;
+}
+
+// The error code and error message sent by the server when an error occurs.
+message ErrorResponse {
+  // This field uses the error codes defined in grpc::StatusCode.
+  int32 error_code = 1;
+  string error_message = 2;
+}
diff --git a/protocol/triple/reflection/triple_reflection/reflection.triple.go 
b/protocol/triple/reflection/triple_reflection/reflection.triple.go
new file mode 100644
index 000000000..005ab3913
--- /dev/null
+++ b/protocol/triple/reflection/triple_reflection/reflection.triple.go
@@ -0,0 +1,199 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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-triple. DO NOT EDIT.
+//
+// Source: reflection.proto
+package triple_reflection
+
+import (
+       "context"
+       "net/http"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3"
+       "dubbo.apache.org/dubbo-go/v3/client"
+       "dubbo.apache.org/dubbo-go/v3/common"
+       "dubbo.apache.org/dubbo-go/v3/common/constant"
+       "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+       "dubbo.apache.org/dubbo-go/v3/server"
+)
+
+// This is a compile-time assertion to ensure that this generated file and the 
Triple package
+// are compatible. If you get a compiler error that this constant is not 
defined, this code was
+// generated with a version of Triple newer than the one compiled into your 
binary. You can fix the
+// problem by either regenerating this code with an older version of Triple or 
updating the Triple
+// version compiled into your binary.
+const _ = triple_protocol.IsAtLeastVersion0_1_0
+
+const (
+       // ServerReflectionName is the fully-qualified name of the 
ServerReflection service.
+       ServerReflectionName = "dubbo.reflection.v1alpha.ServerReflection"
+)
+
+// These constants are the fully-qualified names of the RPCs defined in this 
package. They're
+// exposed at runtime as procedure and as the final two segments of the HTTP 
route.
+//
+// Note that these are different from the fully-qualified method names used by
+// google.golang.org/protobuf/reflect/protoreflect. To convert from these 
constants to
+// reflection-formatted method names, remove the leading slash and convert the 
remaining slash to a
+// period.
+const (
+       // ServerReflectionServerReflectionInfoProcedure is the fully-qualified 
name of the ServerReflection's ServerReflectionInfo RPC.
+       ServerReflectionServerReflectionInfoProcedure = 
"/dubbo.reflection.v1alpha.ServerReflection/ServerReflectionInfo"
+)
+
+var (
+       _ ServerReflection = (*ServerReflectionImpl)(nil)
+
+       _ ServerReflection_ServerReflectionInfoClient = 
(*ServerReflectionServerReflectionInfoClient)(nil)
+
+       _ ServerReflection_ServerReflectionInfoServer = 
(*ServerReflectionServerReflectionInfoServer)(nil)
+)
+
+// ServerReflection is a client for the 
dubbo.reflection.v1alpha.ServerReflection service.
+type ServerReflection interface {
+       ServerReflectionInfo(ctx context.Context, opts ...client.CallOption) 
(ServerReflection_ServerReflectionInfoClient, error)
+}
+
+// NewServerReflection constructs a client for the 
dubbo.reflection.v1alpha.ServerReflection service.
+func NewServerReflection(cli *client.Client, opts ...client.ReferenceOption) 
(ServerReflection, error) {
+       conn, err := 
cli.DialWithInfo("dubbo.reflection.v1alpha.ServerReflection", 
&ServerReflection_ClientInfo, opts...)
+       if err != nil {
+               return nil, err
+       }
+       return &ServerReflectionImpl{
+               conn: conn,
+       }, nil
+}
+
+func SetConsumerService(srv common.RPCService) {
+       dubbo.SetConsumerServiceWithInfo(srv, &ServerReflection_ClientInfo)
+}
+
+// ServerReflectionImpl implements ServerReflection.
+type ServerReflectionImpl struct {
+       conn *client.Connection
+}
+
+func (c *ServerReflectionImpl) ServerReflectionInfo(ctx context.Context, opts 
...client.CallOption) (ServerReflection_ServerReflectionInfoClient, error) {
+       stream, err := c.conn.CallBidiStream(ctx, "ServerReflectionInfo", 
opts...)
+       if err != nil {
+               return nil, err
+       }
+       rawStream := stream.(*triple_protocol.BidiStreamForClient)
+       return &ServerReflectionServerReflectionInfoClient{rawStream}, nil
+}
+
+type ServerReflection_ServerReflectionInfoClient interface {
+       Spec() triple_protocol.Spec
+       Peer() triple_protocol.Peer
+       Send(*ServerReflectionRequest) error
+       RequestHeader() http.Header
+       CloseRequest() error
+       Recv() (*ServerReflectionResponse, error)
+       ResponseHeader() http.Header
+       ResponseTrailer() http.Header
+       CloseResponse() error
+}
+
+type ServerReflectionServerReflectionInfoClient struct {
+       *triple_protocol.BidiStreamForClient
+}
+
+func (cli *ServerReflectionServerReflectionInfoClient) Send(msg 
*ServerReflectionRequest) error {
+       return cli.BidiStreamForClient.Send(msg)
+}
+
+func (cli *ServerReflectionServerReflectionInfoClient) Recv() 
(*ServerReflectionResponse, error) {
+       msg := new(ServerReflectionResponse)
+       if err := cli.BidiStreamForClient.Receive(msg); err != nil {
+               return nil, err
+       }
+       return msg, nil
+}
+
+var ServerReflection_ClientInfo = client.ClientInfo{
+       InterfaceName: "dubbo.reflection.v1alpha.ServerReflection",
+       MethodNames:   []string{"ServerReflectionInfo"},
+       ConnectionInjectFunc: func(dubboCliRaw interface{}, conn 
*client.Connection) {
+               dubboCli := dubboCliRaw.(*ServerReflectionImpl)
+               dubboCli.conn = conn
+       },
+}
+
+// ServerReflectionHandler is an implementation of the 
dubbo.reflection.v1alpha.ServerReflection service.
+type ServerReflectionHandler interface {
+       ServerReflectionInfo(context.Context, 
ServerReflection_ServerReflectionInfoServer) error
+}
+
+func RegisterServerReflectionHandler(srv *server.Server, hdlr 
ServerReflectionHandler, opts ...server.ServiceOption) error {
+       return srv.Register(hdlr, &ServerReflection_ServiceInfo, opts...)
+}
+
+func SetProviderService(srv common.RPCService) {
+       dubbo.SetProviderServiceWithInfo(srv, &ServerReflection_ServiceInfo)
+}
+
+type ServerReflection_ServerReflectionInfoServer interface {
+       Send(*ServerReflectionResponse) error
+       Recv() (*ServerReflectionRequest, error)
+       Spec() triple_protocol.Spec
+       Peer() triple_protocol.Peer
+       RequestHeader() http.Header
+       ResponseHeader() http.Header
+       ResponseTrailer() http.Header
+       Conn() triple_protocol.StreamingHandlerConn
+}
+
+type ServerReflectionServerReflectionInfoServer struct {
+       *triple_protocol.BidiStream
+}
+
+func (srv *ServerReflectionServerReflectionInfoServer) Send(msg 
*ServerReflectionResponse) error {
+       return srv.BidiStream.Send(msg)
+}
+
+func (srv ServerReflectionServerReflectionInfoServer) Recv() 
(*ServerReflectionRequest, error) {
+       msg := new(ServerReflectionRequest)
+       if err := srv.BidiStream.Receive(msg); err != nil {
+               return nil, err
+       }
+       return msg, nil
+}
+
+var ServerReflection_ServiceInfo = server.ServiceInfo{
+       InterfaceName: "dubbo.reflection.v1alpha.ServerReflection",
+       ServiceType:   (*ServerReflectionHandler)(nil),
+       Methods: []server.MethodInfo{
+               {
+                       Name: "ServerReflectionInfo",
+                       Type: constant.CallBidiStream,
+                       StreamInitFunc: func(baseStream interface{}) 
interface{} {
+                               return 
&ServerReflectionServerReflectionInfoServer{baseStream.(*triple_protocol.BidiStream)}
+                       },
+                       MethodFunc: func(ctx context.Context, args 
[]interface{}, handler interface{}) (interface{}, error) {
+                               stream := 
args[0].(ServerReflection_ServerReflectionInfoServer)
+                               if err := 
handler.(ServerReflectionHandler).ServerReflectionInfo(ctx, stream); err != nil 
{
+                                       return nil, err
+                               }
+                               return nil, nil
+                       },
+               },
+       },
+}
diff --git a/protocol/triple/server.go b/protocol/triple/server.go
index b6ea60a53..847b050a0 100644
--- a/protocol/triple/server.go
+++ b/protocol/triple/server.go
@@ -33,6 +33,8 @@ import (
 
        "golang.org/x/net/http2"
        "golang.org/x/net/http2/h2c"
+
+       "google.golang.org/grpc"
 )
 
 import (
@@ -42,6 +44,7 @@ import (
        "dubbo.apache.org/dubbo-go/v3/protocol"
        "dubbo.apache.org/dubbo-go/v3/protocol/dubbo3"
        "dubbo.apache.org/dubbo-go/v3/protocol/invocation"
+       "dubbo.apache.org/dubbo-go/v3/protocol/triple/reflection"
        tri "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
        "dubbo.apache.org/dubbo-go/v3/server"
 )
@@ -50,6 +53,8 @@ import (
 type Server struct {
        httpServer *http.Server
        handler    *http.ServeMux
+       services   map[string]grpc.ServiceInfo
+       mu         sync.RWMutex
 }
 
 // NewServer creates a new TRIPLE server
@@ -114,11 +119,12 @@ func (s *Server) Start(invoker protocol.Invoker, info 
*server.ServiceInfo) {
                mux := s.handler
                if info != nil {
                        handleServiceWithInfo(invoker, info, mux, hanOpts...)
+                       s.saveServiceInfo(info)
                } else {
                        compatHandleService(URL, mux)
                }
                // todo: figure it out this process
-               //reflection.Register(server)
+               reflection.Register(s)
                // todo: without tls
                if cfg == nil {
                        srv.Handler = h2c.NewHandler(mux, &http2.Server{})
@@ -150,6 +156,7 @@ func (s *Server) RefreshService(invoker protocol.Invoker, 
info *server.ServiceIn
        mux := s.handler
        if info != nil {
                handleServiceWithInfo(invoker, info, mux, hanOpts...)
+               s.saveServiceInfo(info)
        } else {
                compatHandleService(URL, mux)
        }
@@ -339,6 +346,47 @@ func handleServiceWithInfo(invoker protocol.Invoker, info 
*server.ServiceInfo, m
        }
 }
 
+func (s *Server) saveServiceInfo(info *server.ServiceInfo) {
+       ret := grpc.ServiceInfo{}
+       ret.Methods = make([]grpc.MethodInfo, 0, len(info.Methods))
+       for _, method := range info.Methods {
+               md := grpc.MethodInfo{}
+               md.Name = method.Name
+               switch method.Type {
+               case constant.CallUnary:
+                       md.IsClientStream = false
+                       md.IsServerStream = false
+               case constant.CallBidiStream:
+                       md.IsClientStream = true
+                       md.IsServerStream = true
+               case constant.CallClientStream:
+                       md.IsClientStream = true
+                       md.IsServerStream = false
+               case constant.CallServerStream:
+                       md.IsClientStream = false
+                       md.IsServerStream = true
+               }
+               ret.Methods = append(ret.Methods, md)
+       }
+       ret.Metadata = info
+       s.mu.Lock()
+       defer s.mu.Unlock()
+       if s.services == nil {
+               s.services = make(map[string]grpc.ServiceInfo)
+       }
+       s.services[info.InterfaceName] = ret
+}
+
+func (s *Server) GetServiceInfo() map[string]grpc.ServiceInfo {
+       s.mu.RLock()
+       defer s.mu.RUnlock()
+       res := make(map[string]grpc.ServiceInfo, len(s.services))
+       for k, v := range s.services {
+               res[k] = v
+       }
+       return res
+}
+
 // Stop TRIPLE server
 func (s *Server) Stop() {
        // todo: process error
diff --git a/protocol/triple/triple.go b/protocol/triple/triple.go
index 37217164d..de083aafc 100644
--- a/protocol/triple/triple.go
+++ b/protocol/triple/triple.go
@@ -92,6 +92,7 @@ func (tp *TripleProtocol) openServer(invoker 
protocol.Invoker, info *server.Serv
                tp.serverMap[url.Location].RefreshService(invoker, info)
                return
        }
+
        if _, ok := tp.ExporterMap().Load(url.ServiceKey()); !ok {
                panic("[TRIPLE Protocol]" + url.Key() + "is not existing")
        }

Reply via email to