1 /*
2  *
3  * Copyright 2016 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 #ifndef GRPC_TEST_CPP_PROTO_SERVER_REFLECTION_DATABSE_H
19 #define GRPC_TEST_CPP_PROTO_SERVER_REFLECTION_DATABSE_H
20 
21 #include <mutex>
22 #include <unordered_map>
23 #include <unordered_set>
24 #include <vector>
25 
26 #include <grpcpp/grpcpp.h>
27 #include <grpcpp/impl/codegen/config_protobuf.h>
28 #include "src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h"
29 
30 namespace grpc {
31 
32 // ProtoReflectionDescriptorDatabase takes a stub of ServerReflection and
33 // provides the methods defined by DescriptorDatabase interfaces. It can be used
34 // to feed a DescriptorPool instance.
35 class ProtoReflectionDescriptorDatabase : public protobuf::DescriptorDatabase {
36  public:
37   explicit ProtoReflectionDescriptorDatabase(
38       std::unique_ptr<reflection::v1alpha::ServerReflection::Stub> stub);
39 
40   explicit ProtoReflectionDescriptorDatabase(
41       const std::shared_ptr<grpc::Channel>& channel);
42 
43   virtual ~ProtoReflectionDescriptorDatabase();
44 
45   // The following four methods implement DescriptorDatabase interfaces.
46   //
47   // Find a file by file name.  Fills in in *output and returns true if found.
48   // Otherwise, returns false, leaving the contents of *output undefined.
49   bool FindFileByName(const string& filename,
50                       protobuf::FileDescriptorProto* output) override;
51 
52   // Find the file that declares the given fully-qualified symbol name.
53   // If found, fills in *output and returns true, otherwise returns false
54   // and leaves *output undefined.
55   bool FindFileContainingSymbol(const string& symbol_name,
56                                 protobuf::FileDescriptorProto* output) override;
57 
58   // Find the file which defines an extension extending the given message type
59   // with the given field number.  If found, fills in *output and returns true,
60   // otherwise returns false and leaves *output undefined.  containing_type
61   // must be a fully-qualified type name.
62   bool FindFileContainingExtension(
63       const string& containing_type, int field_number,
64       protobuf::FileDescriptorProto* output) override;
65 
66   // Finds the tag numbers used by all known extensions of
67   // extendee_type, and appends them to output in an undefined
68   // order. This method is best-effort: it's not guaranteed that the
69   // database will find all extensions, and it's not guaranteed that
70   // FindFileContainingExtension will return true on all of the found
71   // numbers. Returns true if the search was successful, otherwise
72   // returns false and leaves output unchanged.
73   bool FindAllExtensionNumbers(const string& extendee_type,
74                                std::vector<int>* output) override;
75 
76   // Provide a list of full names of registered services
77   bool GetServices(std::vector<grpc::string>* output);
78 
79  private:
80   typedef ClientReaderWriter<
81       grpc::reflection::v1alpha::ServerReflectionRequest,
82       grpc::reflection::v1alpha::ServerReflectionResponse>
83       ClientStream;
84 
85   const protobuf::FileDescriptorProto ParseFileDescriptorProtoResponse(
86       const grpc::string& byte_fd_proto);
87 
88   void AddFileFromResponse(
89       const grpc::reflection::v1alpha::FileDescriptorResponse& response);
90 
91   const std::shared_ptr<ClientStream> GetStream();
92 
93   bool DoOneRequest(
94       const grpc::reflection::v1alpha::ServerReflectionRequest& request,
95       grpc::reflection::v1alpha::ServerReflectionResponse& response);
96 
97   std::shared_ptr<ClientStream> stream_;
98   grpc::ClientContext ctx_;
99   std::unique_ptr<grpc::reflection::v1alpha::ServerReflection::Stub> stub_;
100   std::unordered_set<string> known_files_;
101   std::unordered_set<string> missing_symbols_;
102   std::unordered_map<string, std::unordered_set<int>> missing_extensions_;
103   std::unordered_map<string, std::vector<int>> cached_extension_numbers_;
104   std::mutex stream_mutex_;
105 
106   protobuf::SimpleDescriptorDatabase cached_db_;
107 };
108 
109 }  // namespace grpc
110 
111 #endif  // GRPC_TEST_CPP_METRICS_SERVER_H
112