2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
19
20
22#include <grpc-reflection/proto_server_reflection.hpp>
25#include <unordered_set>
28#include <grpcpp/grpcpp.h>
29#include <grpcpp/support/interceptor.h>
33namespace proto_reflection = grpc::reflection::v1alpha;
35USERVER_NAMESPACE_BEGIN
39ProtoServerReflection::ProtoServerReflection() : descriptor_pool_(grpc::protobuf::DescriptorPool::generated_pool()) {}
41void ProtoServerReflection::AddService(std::string_view service) {
42 auto ptr = services_.Lock();
43 ptr->insert(std::move(service));
46void ProtoServerReflection::AddServiceList(
const std::vector<std::string_view>& services) {
47 auto ptr = services_.Lock();
48 for (
auto&& service : services) {
49 ptr->insert(std::move(service));
53ProtoServerReflection::ServerReflectionInfoResult
54ProtoServerReflection::ServerReflectionInfo(CallContext& , ServerReflectionInfoReaderWriter& stream) {
55 proto_reflection::ServerReflectionRequest request;
56 proto_reflection::ServerReflectionResponse response;
57 ::grpc::Status status;
58 while (stream.Read(request)) {
59 switch (request.message_request_case()) {
60 case proto_reflection::ServerReflectionRequest::MessageRequestCase::kFileByFilename:
61 status = GetFileByName(request.file_by_filename(), response);
63 case proto_reflection::ServerReflectionRequest::MessageRequestCase::kFileContainingSymbol:
64 status = GetFileContainingSymbol(request.file_containing_symbol(), response);
66 case proto_reflection::ServerReflectionRequest::MessageRequestCase::kFileContainingExtension:
67 status = GetFileContainingExtension(request.file_containing_extension(), response);
69 case proto_reflection::ServerReflectionRequest::MessageRequestCase::kAllExtensionNumbersOfType:
70 status = GetAllExtensionNumbers(
71 request.all_extension_numbers_of_type(), *response.mutable_all_extension_numbers_response()
74 case proto_reflection::ServerReflectionRequest::MessageRequestCase::kListServices:
75 status = ListService(*response.mutable_list_services_response());
78 status = ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED,
"");
82 FillErrorResponse(status, *response.mutable_error_response());
84 response.set_valid_host(request.host());
85 response.set_allocated_original_request(
new proto_reflection::ServerReflectionRequest(request));
86 stream.Write(response);
89 return grpc::Status::OK;
92void ProtoServerReflection::FillErrorResponse(
93 const ::grpc::Status& status,
94 proto_reflection::ErrorResponse& error_response
96 error_response.set_error_code(status.error_code());
97 error_response.set_error_message(status.error_message());
100::grpc::Status ProtoServerReflection::ListService(proto_reflection::ListServiceResponse& response) {
101 auto ptr = services_.Lock();
103 return ::grpc::Status(::grpc::StatusCode::NOT_FOUND,
"Services not found.");
105 for (
const auto& value : *ptr) {
106 proto_reflection::ServiceResponse* service_response = response.add_service();
107 *service_response->mutable_name() = value;
109 return ::grpc::Status::OK;
113ProtoServerReflection::GetFileByName(std::string_view file_name, proto_reflection::ServerReflectionResponse& response) {
114 if (descriptor_pool_ ==
nullptr) {
115 return ::grpc::Status::CANCELLED;
118 const grpc::protobuf::FileDescriptor* file_desc =
119#if GOOGLE_PROTOBUF_VERSION
>= 3022000
120 descriptor_pool_->FindFileByName(file_name);
122 descriptor_pool_->FindFileByName(std::string{file_name});
124 if (file_desc ==
nullptr) {
125 return ::grpc::Status(::grpc::StatusCode::NOT_FOUND,
"File not found.");
127 std::unordered_set<std::string_view> seen_files;
128 FillFileDescriptorResponse(*file_desc, response, seen_files);
129 return ::grpc::Status::OK;
132::grpc::Status ProtoServerReflection::GetFileContainingSymbol(
133 std::string_view symbol,
134 proto_reflection::ServerReflectionResponse& response
136 if (descriptor_pool_ ==
nullptr) {
137 return ::grpc::Status::CANCELLED;
140#if GOOGLE_PROTOBUF_VERSION
>= 3022000
141 const grpc::protobuf::FileDescriptor* file_desc = descriptor_pool_->FindFileContainingSymbol(symbol);
143 const grpc::protobuf::FileDescriptor* file_desc = descriptor_pool_->FindFileContainingSymbol(std::string{symbol});
145 if (file_desc ==
nullptr) {
146 return ::grpc::Status(::grpc::StatusCode::NOT_FOUND,
"Symbol not found.");
148 std::unordered_set<std::string_view> seen_files;
149 FillFileDescriptorResponse(*file_desc, response, seen_files);
150 return ::grpc::Status::OK;
153::grpc::Status ProtoServerReflection::GetFileContainingExtension(
154 const proto_reflection::ExtensionRequest& request,
155 proto_reflection::ServerReflectionResponse& response
157 if (descriptor_pool_ ==
nullptr) {
158 return ::grpc::Status::CANCELLED;
161 const grpc::protobuf::Descriptor* desc = descriptor_pool_->FindMessageTypeByName(request.containing_type());
162 if (desc ==
nullptr) {
163 return ::grpc::Status(::grpc::StatusCode::NOT_FOUND,
"Type not found.");
166 const grpc::protobuf::FieldDescriptor* field_desc =
167 descriptor_pool_->FindExtensionByNumber(desc, request.extension_number());
168 if (field_desc ==
nullptr) {
169 return ::grpc::Status(::grpc::StatusCode::NOT_FOUND,
"Extension not found.");
171 std::unordered_set<std::string_view> seen_files;
172 FillFileDescriptorResponse(*(field_desc->file()), response, seen_files);
173 return ::grpc::Status::OK;
176::grpc::Status ProtoServerReflection::GetAllExtensionNumbers(
177 std::string_view type,
178 proto_reflection::ExtensionNumberResponse& response
180 if (descriptor_pool_ ==
nullptr) {
181 return ::grpc::Status::CANCELLED;
184#if GOOGLE_PROTOBUF_VERSION
>= 3022000
185 const grpc::protobuf::Descriptor* desc = descriptor_pool_->FindMessageTypeByName(type);
187 const grpc::protobuf::Descriptor* desc = descriptor_pool_->FindMessageTypeByName(std::string{type});
189 if (desc ==
nullptr) {
190 return ::grpc::Status(::grpc::StatusCode::NOT_FOUND,
"Type not found.");
193 std::vector<
const grpc::protobuf::FieldDescriptor*> extensions;
194 descriptor_pool_->FindAllExtensions(desc, &extensions);
195 for (
const auto& value : extensions) {
196 response.add_extension_number(value->number());
198 *response.mutable_base_type_name() = type;
199 return ::grpc::Status::OK;
202void ProtoServerReflection::FillFileDescriptorResponse(
203 const grpc::protobuf::FileDescriptor& file_desc,
204 proto_reflection::ServerReflectionResponse& response,
205 std::unordered_set<std::string_view>& seen_files
207 if (seen_files.find(file_desc.name()) != seen_files.end()) {
210 seen_files.insert(file_desc.name());
212 grpc::protobuf::FileDescriptorProto file_desc_proto;
214 file_desc.CopyTo(&file_desc_proto);
215 if (!file_desc_proto.SerializeToString(&data)) {
216 throw std::runtime_error(
"Failed to serialize file_desc_proto to string");
218 response.mutable_file_descriptor_response()->add_file_descriptor_proto(data);
220 for (
int i = 0; i < file_desc.dependency_count(); ++i) {
221 FillFileDescriptorResponse(*file_desc.dependency(i), response, seen_files);