proto_reflection_descriptor_database.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  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. #include "test/cpp/util/proto_reflection_descriptor_database.h"
  19. #include <vector>
  20. #include <grpc/support/log.h>
  21. using grpc::reflection::v1alpha::ErrorResponse;
  22. using grpc::reflection::v1alpha::ListServiceResponse;
  23. using grpc::reflection::v1alpha::ServerReflection;
  24. using grpc::reflection::v1alpha::ServerReflectionRequest;
  25. using grpc::reflection::v1alpha::ServerReflectionResponse;
  26. namespace grpc {
  27. ProtoReflectionDescriptorDatabase::ProtoReflectionDescriptorDatabase(
  28. std::unique_ptr<ServerReflection::Stub> stub)
  29. : stub_(std::move(stub)) {}
  30. ProtoReflectionDescriptorDatabase::ProtoReflectionDescriptorDatabase(
  31. const std::shared_ptr<grpc::Channel>& channel)
  32. : stub_(ServerReflection::NewStub(channel)) {}
  33. ProtoReflectionDescriptorDatabase::~ProtoReflectionDescriptorDatabase() {
  34. if (stream_) {
  35. stream_->WritesDone();
  36. Status status = stream_->Finish();
  37. if (!status.ok()) {
  38. if (status.error_code() == StatusCode::UNIMPLEMENTED) {
  39. fprintf(stderr,
  40. "Reflection request not implemented; "
  41. "is the ServerReflection service enabled?\n");
  42. } else {
  43. fprintf(stderr,
  44. "ServerReflectionInfo rpc failed. Error code: %d, message: %s, "
  45. "debug info: %s\n",
  46. static_cast<int>(status.error_code()),
  47. status.error_message().c_str(),
  48. ctx_.debug_error_string().c_str());
  49. }
  50. }
  51. }
  52. }
  53. bool ProtoReflectionDescriptorDatabase::FindFileByName(
  54. const string& filename, protobuf::FileDescriptorProto* output) {
  55. if (cached_db_.FindFileByName(filename, output)) {
  56. return true;
  57. }
  58. if (known_files_.find(filename) != known_files_.end()) {
  59. return false;
  60. }
  61. ServerReflectionRequest request;
  62. request.set_file_by_filename(filename);
  63. ServerReflectionResponse response;
  64. if (!DoOneRequest(request, response)) {
  65. return false;
  66. }
  67. if (response.message_response_case() ==
  68. ServerReflectionResponse::MessageResponseCase::kFileDescriptorResponse) {
  69. AddFileFromResponse(response.file_descriptor_response());
  70. } else if (response.message_response_case() ==
  71. ServerReflectionResponse::MessageResponseCase::kErrorResponse) {
  72. const ErrorResponse& error = response.error_response();
  73. if (error.error_code() == StatusCode::NOT_FOUND) {
  74. gpr_log(GPR_INFO, "NOT_FOUND from server for FindFileByName(%s)",
  75. filename.c_str());
  76. } else {
  77. gpr_log(GPR_INFO,
  78. "Error on FindFileByName(%s)\n\tError code: %d\n"
  79. "\tError Message: %s",
  80. filename.c_str(), error.error_code(),
  81. error.error_message().c_str());
  82. }
  83. } else {
  84. gpr_log(
  85. GPR_INFO,
  86. "Error on FindFileByName(%s) response type\n"
  87. "\tExpecting: %d\n\tReceived: %d",
  88. filename.c_str(),
  89. ServerReflectionResponse::MessageResponseCase::kFileDescriptorResponse,
  90. response.message_response_case());
  91. }
  92. return cached_db_.FindFileByName(filename, output);
  93. }
  94. bool ProtoReflectionDescriptorDatabase::FindFileContainingSymbol(
  95. const string& symbol_name, protobuf::FileDescriptorProto* output) {
  96. if (cached_db_.FindFileContainingSymbol(symbol_name, output)) {
  97. return true;
  98. }
  99. if (missing_symbols_.find(symbol_name) != missing_symbols_.end()) {
  100. return false;
  101. }
  102. ServerReflectionRequest request;
  103. request.set_file_containing_symbol(symbol_name);
  104. ServerReflectionResponse response;
  105. if (!DoOneRequest(request, response)) {
  106. return false;
  107. }
  108. if (response.message_response_case() ==
  109. ServerReflectionResponse::MessageResponseCase::kFileDescriptorResponse) {
  110. AddFileFromResponse(response.file_descriptor_response());
  111. } else if (response.message_response_case() ==
  112. ServerReflectionResponse::MessageResponseCase::kErrorResponse) {
  113. const ErrorResponse& error = response.error_response();
  114. if (error.error_code() == StatusCode::NOT_FOUND) {
  115. missing_symbols_.insert(symbol_name);
  116. gpr_log(GPR_INFO,
  117. "NOT_FOUND from server for FindFileContainingSymbol(%s)",
  118. symbol_name.c_str());
  119. } else {
  120. gpr_log(GPR_INFO,
  121. "Error on FindFileContainingSymbol(%s)\n"
  122. "\tError code: %d\n\tError Message: %s",
  123. symbol_name.c_str(), error.error_code(),
  124. error.error_message().c_str());
  125. }
  126. } else {
  127. gpr_log(
  128. GPR_INFO,
  129. "Error on FindFileContainingSymbol(%s) response type\n"
  130. "\tExpecting: %d\n\tReceived: %d",
  131. symbol_name.c_str(),
  132. ServerReflectionResponse::MessageResponseCase::kFileDescriptorResponse,
  133. response.message_response_case());
  134. }
  135. return cached_db_.FindFileContainingSymbol(symbol_name, output);
  136. }
  137. bool ProtoReflectionDescriptorDatabase::FindFileContainingExtension(
  138. const string& containing_type, int field_number,
  139. protobuf::FileDescriptorProto* output) {
  140. if (cached_db_.FindFileContainingExtension(containing_type, field_number,
  141. output)) {
  142. return true;
  143. }
  144. if (missing_extensions_.find(containing_type) != missing_extensions_.end() &&
  145. missing_extensions_[containing_type].find(field_number) !=
  146. missing_extensions_[containing_type].end()) {
  147. gpr_log(GPR_INFO, "nested map.");
  148. return false;
  149. }
  150. ServerReflectionRequest request;
  151. request.mutable_file_containing_extension()->set_containing_type(
  152. containing_type);
  153. request.mutable_file_containing_extension()->set_extension_number(
  154. field_number);
  155. ServerReflectionResponse response;
  156. if (!DoOneRequest(request, response)) {
  157. return false;
  158. }
  159. if (response.message_response_case() ==
  160. ServerReflectionResponse::MessageResponseCase::kFileDescriptorResponse) {
  161. AddFileFromResponse(response.file_descriptor_response());
  162. } else if (response.message_response_case() ==
  163. ServerReflectionResponse::MessageResponseCase::kErrorResponse) {
  164. const ErrorResponse& error = response.error_response();
  165. if (error.error_code() == StatusCode::NOT_FOUND) {
  166. if (missing_extensions_.find(containing_type) ==
  167. missing_extensions_.end()) {
  168. missing_extensions_[containing_type] = {};
  169. }
  170. missing_extensions_[containing_type].insert(field_number);
  171. gpr_log(GPR_INFO,
  172. "NOT_FOUND from server for FindFileContainingExtension(%s, %d)",
  173. containing_type.c_str(), field_number);
  174. } else {
  175. gpr_log(GPR_INFO,
  176. "Error on FindFileContainingExtension(%s, %d)\n"
  177. "\tError code: %d\n\tError Message: %s",
  178. containing_type.c_str(), field_number, error.error_code(),
  179. error.error_message().c_str());
  180. }
  181. } else {
  182. gpr_log(
  183. GPR_INFO,
  184. "Error on FindFileContainingExtension(%s, %d) response type\n"
  185. "\tExpecting: %d\n\tReceived: %d",
  186. containing_type.c_str(), field_number,
  187. ServerReflectionResponse::MessageResponseCase::kFileDescriptorResponse,
  188. response.message_response_case());
  189. }
  190. return cached_db_.FindFileContainingExtension(containing_type, field_number,
  191. output);
  192. }
  193. bool ProtoReflectionDescriptorDatabase::FindAllExtensionNumbers(
  194. const string& extendee_type, std::vector<int>* output) {
  195. if (cached_extension_numbers_.find(extendee_type) !=
  196. cached_extension_numbers_.end()) {
  197. *output = cached_extension_numbers_[extendee_type];
  198. return true;
  199. }
  200. ServerReflectionRequest request;
  201. request.set_all_extension_numbers_of_type(extendee_type);
  202. ServerReflectionResponse response;
  203. if (!DoOneRequest(request, response)) {
  204. return false;
  205. }
  206. if (response.message_response_case() ==
  207. ServerReflectionResponse::MessageResponseCase::
  208. kAllExtensionNumbersResponse) {
  209. auto number = response.all_extension_numbers_response().extension_number();
  210. *output = std::vector<int>(number.begin(), number.end());
  211. cached_extension_numbers_[extendee_type] = *output;
  212. return true;
  213. } else if (response.message_response_case() ==
  214. ServerReflectionResponse::MessageResponseCase::kErrorResponse) {
  215. const ErrorResponse& error = response.error_response();
  216. if (error.error_code() == StatusCode::NOT_FOUND) {
  217. gpr_log(GPR_INFO, "NOT_FOUND from server for FindAllExtensionNumbers(%s)",
  218. extendee_type.c_str());
  219. } else {
  220. gpr_log(GPR_INFO,
  221. "Error on FindAllExtensionNumbersExtension(%s)\n"
  222. "\tError code: %d\n\tError Message: %s",
  223. extendee_type.c_str(), error.error_code(),
  224. error.error_message().c_str());
  225. }
  226. }
  227. return false;
  228. }
  229. bool ProtoReflectionDescriptorDatabase::GetServices(
  230. std::vector<std::string>* output) {
  231. ServerReflectionRequest request;
  232. request.set_list_services("");
  233. ServerReflectionResponse response;
  234. if (!DoOneRequest(request, response)) {
  235. return false;
  236. }
  237. if (response.message_response_case() ==
  238. ServerReflectionResponse::MessageResponseCase::kListServicesResponse) {
  239. const ListServiceResponse& ls_response = response.list_services_response();
  240. for (int i = 0; i < ls_response.service_size(); ++i) {
  241. (*output).push_back(ls_response.service(i).name());
  242. }
  243. return true;
  244. } else if (response.message_response_case() ==
  245. ServerReflectionResponse::MessageResponseCase::kErrorResponse) {
  246. const ErrorResponse& error = response.error_response();
  247. gpr_log(GPR_INFO,
  248. "Error on GetServices()\n\tError code: %d\n"
  249. "\tError Message: %s",
  250. error.error_code(), error.error_message().c_str());
  251. } else {
  252. gpr_log(
  253. GPR_INFO,
  254. "Error on GetServices() response type\n\tExpecting: %d\n\tReceived: %d",
  255. ServerReflectionResponse::MessageResponseCase::kListServicesResponse,
  256. response.message_response_case());
  257. }
  258. return false;
  259. }
  260. protobuf::FileDescriptorProto
  261. ProtoReflectionDescriptorDatabase::ParseFileDescriptorProtoResponse(
  262. const std::string& byte_fd_proto) {
  263. protobuf::FileDescriptorProto file_desc_proto;
  264. file_desc_proto.ParseFromString(byte_fd_proto);
  265. return file_desc_proto;
  266. }
  267. void ProtoReflectionDescriptorDatabase::AddFileFromResponse(
  268. const grpc::reflection::v1alpha::FileDescriptorResponse& response) {
  269. for (int i = 0; i < response.file_descriptor_proto_size(); ++i) {
  270. const protobuf::FileDescriptorProto file_proto =
  271. ParseFileDescriptorProtoResponse(response.file_descriptor_proto(i));
  272. if (known_files_.find(file_proto.name()) == known_files_.end()) {
  273. known_files_.insert(file_proto.name());
  274. cached_db_.Add(file_proto);
  275. }
  276. }
  277. }
  278. std::shared_ptr<ProtoReflectionDescriptorDatabase::ClientStream>
  279. ProtoReflectionDescriptorDatabase::GetStream() {
  280. if (!stream_) {
  281. stream_ = stub_->ServerReflectionInfo(&ctx_);
  282. }
  283. return stream_;
  284. }
  285. bool ProtoReflectionDescriptorDatabase::DoOneRequest(
  286. const ServerReflectionRequest& request,
  287. ServerReflectionResponse& response) {
  288. bool success = false;
  289. stream_mutex_.lock();
  290. if (GetStream()->Write(request) && GetStream()->Read(&response)) {
  291. success = true;
  292. }
  293. stream_mutex_.unlock();
  294. return success;
  295. }
  296. } // namespace grpc