diff --git a/extensions/reflection/proto_server_reflection.cc b/extensions/reflection/proto_server_reflection.cc index 28292a42d60..fe4564ab723 100644 --- a/extensions/reflection/proto_server_reflection.cc +++ b/extensions/reflection/proto_server_reflection.cc @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -146,7 +147,8 @@ Status ProtoServerReflection::GetFileByName( if (file_desc == nullptr) { return Status(StatusCode::NOT_FOUND, "File not found."); } - FillFileDescriptorProtoResponse(file_desc, response); + std::unordered_set seen_files; + FillFileDescriptorResponse(file_desc, response, &seen_files); return Status::OK; } @@ -162,7 +164,8 @@ Status ProtoServerReflection::GetFileContainingSymbol( if (file_desc == nullptr) { return Status(StatusCode::NOT_FOUND, "Symbol not found."); } - FillFileDescriptorProtoResponse(file_desc, response); + std::unordered_set seen_files; + FillFileDescriptorResponse(file_desc, response, &seen_files); return Status::OK; } @@ -184,7 +187,8 @@ Status ProtoServerReflection::GetFileContainingExtension( if (field_desc == nullptr) { return Status(StatusCode::NOT_FOUND, "Extension not found."); } - FillFileDescriptorProtoResponse(field_desc->file(), response); + std::unordered_set seen_files; + FillFileDescriptorResponse(field_desc->file(), response, &seen_files); return Status::OK; } @@ -209,13 +213,23 @@ Status ProtoServerReflection::GetAllExtensionNumbers( return Status::OK; } -void ProtoServerReflection::FillFileDescriptorProtoResponse( - const FileDescriptor* file_desc, ServerReflectionResponse* response) { +void ProtoServerReflection::FillFileDescriptorResponse( + const FileDescriptor* file_desc, ServerReflectionResponse* response, + std::unordered_set* seen_files) { + if (seen_files->find(file_desc->name()) != seen_files->end()) { + return; + } + seen_files->insert(file_desc->name()); + FileDescriptorProto file_desc_proto; grpc::string data; file_desc->CopyTo(&file_desc_proto); file_desc_proto.SerializeToString(&data); response->mutable_file_descriptor_response()->add_file_descriptor_proto(data); + + for (int i = 0; i < file_desc->dependency_count(); ++i) { + FillFileDescriptorResponse(file_desc->dependency(i), response, seen_files); + } } } // namespace grpc diff --git a/extensions/reflection/proto_server_reflection.h b/extensions/reflection/proto_server_reflection.h index 53deef906cf..d288b73d928 100644 --- a/extensions/reflection/proto_server_reflection.h +++ b/extensions/reflection/proto_server_reflection.h @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -81,9 +82,10 @@ class ProtoServerReflection GRPC_FINAL ServerContext* context, const grpc::string& type, reflection::v1alpha::ExtensionNumberResponse* response); - void FillFileDescriptorProtoResponse( + void FillFileDescriptorResponse( const google::protobuf::FileDescriptor* file_desc, - reflection::v1alpha::ServerReflectionResponse* response); + reflection::v1alpha::ServerReflectionResponse* response, + std::unordered_set* seen_files); void FillErrorResponse(const Status& status, reflection::v1alpha::ErrorResponse* error_response);