github.com/xiaoshude/protoreflect@v1.16.1-0.20220310024924-8c94d7247598/grpcreflect/server.go (about) 1 package grpcreflect 2 3 import ( 4 "fmt" 5 6 "google.golang.org/grpc" 7 8 "github.com/xiaoshude/protoreflect/desc" 9 ) 10 11 // LoadServiceDescriptors loads the service descriptors for all services exposed by the 12 // given GRPC server. 13 func LoadServiceDescriptors(s *grpc.Server) (map[string]*desc.ServiceDescriptor, error) { 14 descs := map[string]*desc.ServiceDescriptor{} 15 for name, info := range s.GetServiceInfo() { 16 file, ok := info.Metadata.(string) 17 if !ok { 18 return nil, fmt.Errorf("service %q has unexpected metadata: expecting a string; got %v", name, info.Metadata) 19 } 20 fd, err := desc.LoadFileDescriptor(file) 21 if err != nil { 22 return nil, err 23 } 24 d := fd.FindSymbol(name) 25 if d == nil { 26 return nil, fmt.Errorf("file descriptor for %q has no element named %q", file, name) 27 } 28 sd, ok := d.(*desc.ServiceDescriptor) 29 if !ok { 30 return nil, fmt.Errorf("file descriptor for %q has incorrect element named %q: expecting a service descriptor; got %v", file, name, d) 31 } 32 descs[name] = sd 33 } 34 return descs, nil 35 } 36 37 // LoadServiceDescriptor loads a rich descriptor for a given service description 38 // generated by protoc-gen-go. Generated code contains an unexported symbol with 39 // a name like "_<Service>_serviceDesc" which is the service's description. It 40 // is used internally to register a service implementation with a GRPC server. 41 // But it can also be used by this package to retrieve the rich descriptor for 42 // the service. 43 func LoadServiceDescriptor(svc *grpc.ServiceDesc) (*desc.ServiceDescriptor, error) { 44 file, ok := svc.Metadata.(string) 45 if !ok { 46 return nil, fmt.Errorf("service %q has unexpected metadata: expecting a string; got %v", svc.ServiceName, svc.Metadata) 47 } 48 fd, err := desc.LoadFileDescriptor(file) 49 if err != nil { 50 return nil, err 51 } 52 d := fd.FindSymbol(svc.ServiceName) 53 if d == nil { 54 return nil, fmt.Errorf("file descriptor for %q has no element named %q", file, svc.ServiceName) 55 } 56 sd, ok := d.(*desc.ServiceDescriptor) 57 if !ok { 58 return nil, fmt.Errorf("file descriptor for %q has incorrect element named %q: expecting a service descriptor; got %v", file, svc.ServiceName, d) 59 } 60 return sd, nil 61 }