| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998 | 
							- /*
 
-  *
 
-  * Copyright 2016 gRPC authors.
 
-  *
 
-  * Licensed under the Apache License, Version 2.0 (the "License");
 
-  * you may not use this file except in compliance with the License.
 
-  * You may obtain a copy of the License at
 
-  *
 
-  *     http://www.apache.org/licenses/LICENSE-2.0
 
-  *
 
-  * Unless required by applicable law or agreed to in writing, software
 
-  * distributed under the License is distributed on an "AS IS" BASIS,
 
-  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
-  * See the License for the specific language governing permissions and
 
-  * limitations under the License.
 
-  *
 
-  */
 
- #include "test/cpp/util/grpc_tool.h"
 
- #include <grpc/grpc.h>
 
- #include <grpc/support/port_platform.h>
 
- #include <grpcpp/channel.h>
 
- #include <grpcpp/create_channel.h>
 
- #include <grpcpp/grpcpp.h>
 
- #include <grpcpp/security/credentials.h>
 
- #include <grpcpp/support/string_ref.h>
 
- #include <cstdio>
 
- #include <fstream>
 
- #include <iostream>
 
- #include <memory>
 
- #include <sstream>
 
- #include <string>
 
- #include <thread>
 
- #include "absl/flags/flag.h"
 
- #include "absl/memory/memory.h"
 
- #include "test/cpp/util/cli_call.h"
 
- #include "test/cpp/util/proto_file_parser.h"
 
- #include "test/cpp/util/proto_reflection_descriptor_database.h"
 
- #include "test/cpp/util/service_describer.h"
 
- #if GPR_WINDOWS
 
- #include <io.h>
 
- #else
 
- #include <unistd.h>
 
- #endif
 
- ABSL_FLAG(bool, l, false, "Use a long listing format");
 
- ABSL_FLAG(bool, remotedb, true,
 
-           "Use server types to parse and format messages");
 
- ABSL_FLAG(std::string, metadata, "",
 
-           "Metadata to send to server, in the form of key1:val1:key2:val2");
 
- ABSL_FLAG(std::string, proto_path, ".", "Path to look for the proto file.");
 
- ABSL_FLAG(std::string, protofiles, "", "Name of the proto file.");
 
- ABSL_FLAG(bool, binary_input, false, "Input in binary format");
 
- ABSL_FLAG(bool, binary_output, false, "Output in binary format");
 
- ABSL_FLAG(std::string, default_service_config, "",
 
-           "Default service config to use on the channel, if non-empty. Note "
 
-           "that this will be ignored if the name resolver returns a service "
 
-           "config.");
 
- ABSL_FLAG(bool, display_peer_address, false,
 
-           "Log the peer socket address of the connection that each RPC is made "
 
-           "on to stderr.");
 
- ABSL_FLAG(bool, json_input, false, "Input in json format");
 
- ABSL_FLAG(bool, json_output, false, "Output in json format");
 
- ABSL_FLAG(std::string, infile, "", "Input file (default is stdin)");
 
- ABSL_FLAG(bool, batch, false,
 
-           "Input contains multiple requests. Please do not use this to send "
 
-           "more than a few RPCs. gRPC CLI has very different performance "
 
-           "characteristics compared with normal RPC calls which make it "
 
-           "unsuitable for loadtesting or significant production traffic.");
 
- // TODO(Capstan): Consider using absl::Duration
 
- ABSL_FLAG(double, timeout, -1,
 
-           "Specify timeout in seconds, used to set the deadline for all "
 
-           "RPCs. The default value of -1 means no deadline has been set.");
 
- namespace grpc {
 
- namespace testing {
 
- namespace {
 
- class GrpcTool {
 
-  public:
 
-   explicit GrpcTool();
 
-   virtual ~GrpcTool() {}
 
-   bool Help(int argc, const char** argv, const CliCredentials& cred,
 
-             const GrpcToolOutputCallback& callback);
 
-   bool CallMethod(int argc, const char** argv, const CliCredentials& cred,
 
-                   const GrpcToolOutputCallback& callback);
 
-   bool ListServices(int argc, const char** argv, const CliCredentials& cred,
 
-                     const GrpcToolOutputCallback& callback);
 
-   bool PrintType(int argc, const char** argv, const CliCredentials& cred,
 
-                  const GrpcToolOutputCallback& callback);
 
-   // TODO(zyc): implement the following methods
 
-   // bool ListServices(int argc, const char** argv, GrpcToolOutputCallback
 
-   // callback);
 
-   // bool PrintTypeId(int argc, const char** argv, GrpcToolOutputCallback
 
-   // callback);
 
-   bool ParseMessage(int argc, const char** argv, const CliCredentials& cred,
 
-                     const GrpcToolOutputCallback& callback);
 
-   bool ToText(int argc, const char** argv, const CliCredentials& cred,
 
-               const GrpcToolOutputCallback& callback);
 
-   bool ToJson(int argc, const char** argv, const CliCredentials& cred,
 
-               const GrpcToolOutputCallback& callback);
 
-   bool ToBinary(int argc, const char** argv, const CliCredentials& cred,
 
-                 const GrpcToolOutputCallback& callback);
 
-   void SetPrintCommandMode(int exit_status) {
 
-     print_command_usage_ = true;
 
-     usage_exit_status_ = exit_status;
 
-   }
 
-  private:
 
-   void CommandUsage(const std::string& usage) const;
 
-   bool print_command_usage_;
 
-   int usage_exit_status_;
 
-   const std::string cred_usage_;
 
- };
 
- template <typename T>
 
- std::function<bool(GrpcTool*, int, const char**, const CliCredentials&,
 
-                    GrpcToolOutputCallback)>
 
- BindWith5Args(T&& func) {
 
-   return std::bind(std::forward<T>(func), std::placeholders::_1,
 
-                    std::placeholders::_2, std::placeholders::_3,
 
-                    std::placeholders::_4, std::placeholders::_5);
 
- }
 
- template <typename T>
 
- size_t ArraySize(T& a) {
 
-   return ((sizeof(a) / sizeof(*(a))) /
 
-           static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))));
 
- }
 
- void ParseMetadataFlag(
 
-     std::multimap<std::string, std::string>* client_metadata) {
 
-   if (absl::GetFlag(FLAGS_metadata).empty()) {
 
-     return;
 
-   }
 
-   std::vector<std::string> fields;
 
-   const char delim = ':';
 
-   const char escape = '\\';
 
-   size_t cur = -1;
 
-   std::stringstream ss;
 
-   while (++cur < absl::GetFlag(FLAGS_metadata).length()) {
 
-     switch (absl::GetFlag(FLAGS_metadata).at(cur)) {
 
-       case escape:
 
-         if (cur < absl::GetFlag(FLAGS_metadata).length() - 1) {
 
-           char c = absl::GetFlag(FLAGS_metadata).at(++cur);
 
-           if (c == delim || c == escape) {
 
-             ss << c;
 
-             continue;
 
-           }
 
-         }
 
-         fprintf(stderr, "Failed to parse metadata flag.\n");
 
-         exit(1);
 
-       case delim:
 
-         fields.push_back(ss.str());
 
-         ss.str("");
 
-         ss.clear();
 
-         break;
 
-       default:
 
-         ss << absl::GetFlag(FLAGS_metadata).at(cur);
 
-     }
 
-   }
 
-   fields.push_back(ss.str());
 
-   if (fields.size() % 2) {
 
-     fprintf(stderr, "Failed to parse metadata flag.\n");
 
-     exit(1);
 
-   }
 
-   for (size_t i = 0; i < fields.size(); i += 2) {
 
-     client_metadata->insert(
 
-         std::pair<std::string, std::string>(fields[i], fields[i + 1]));
 
-   }
 
- }
 
- template <typename T>
 
- void PrintMetadata(const T& m, const std::string& message) {
 
-   if (m.empty()) {
 
-     return;
 
-   }
 
-   fprintf(stderr, "%s\n", message.c_str());
 
-   std::string pair;
 
-   for (typename T::const_iterator iter = m.begin(); iter != m.end(); ++iter) {
 
-     pair.clear();
 
-     pair.append(iter->first.data(), iter->first.size());
 
-     pair.append(" : ");
 
-     pair.append(iter->second.data(), iter->second.size());
 
-     fprintf(stderr, "%s\n", pair.c_str());
 
-   }
 
- }
 
- void ReadResponse(CliCall* call, const std::string& method_name,
 
-                   const GrpcToolOutputCallback& callback,
 
-                   ProtoFileParser* parser, gpr_mu* parser_mu, bool print_mode) {
 
-   std::string serialized_response_proto;
 
-   std::multimap<grpc::string_ref, grpc::string_ref> server_initial_metadata;
 
-   for (bool receive_initial_metadata = true; call->ReadAndMaybeNotifyWrite(
 
-            &serialized_response_proto,
 
-            receive_initial_metadata ? &server_initial_metadata : nullptr);
 
-        receive_initial_metadata = false) {
 
-     fprintf(stderr, "got response.\n");
 
-     if (!absl::GetFlag(FLAGS_binary_output)) {
 
-       gpr_mu_lock(parser_mu);
 
-       serialized_response_proto = parser->GetFormattedStringFromMethod(
 
-           method_name, serialized_response_proto, false /* is_request */,
 
-           absl::GetFlag(FLAGS_json_output));
 
-       if (parser->HasError() && print_mode) {
 
-         fprintf(stderr, "Failed to parse response.\n");
 
-       }
 
-       gpr_mu_unlock(parser_mu);
 
-     }
 
-     if (receive_initial_metadata) {
 
-       PrintMetadata(server_initial_metadata,
 
-                     "Received initial metadata from server:");
 
-     }
 
-     if (!callback(serialized_response_proto) && print_mode) {
 
-       fprintf(stderr, "Failed to output response.\n");
 
-     }
 
-   }
 
- }
 
- std::shared_ptr<grpc::Channel> CreateCliChannel(
 
-     const std::string& server_address, const CliCredentials& cred) {
 
-   grpc::ChannelArguments args;
 
-   if (!cred.GetSslTargetNameOverride().empty()) {
 
-     args.SetSslTargetNameOverride(cred.GetSslTargetNameOverride());
 
-   }
 
-   if (!absl::GetFlag(FLAGS_default_service_config).empty()) {
 
-     args.SetString(GRPC_ARG_SERVICE_CONFIG,
 
-                    absl::GetFlag(FLAGS_default_service_config).c_str());
 
-   }
 
-   // See |GRPC_ARG_MAX_METADATA_SIZE| in |grpc_types.h|.
 
-   // Set to large enough size (10M) that should work for most use cases.
 
-   args.SetInt(GRPC_ARG_MAX_METADATA_SIZE, 10 * 1024 * 1024);
 
-   return ::grpc::CreateCustomChannel(server_address, cred.GetCredentials(),
 
-                                      args);
 
- }
 
- struct Command {
 
-   const char* command;
 
-   std::function<bool(GrpcTool*, int, const char**, const CliCredentials&,
 
-                      GrpcToolOutputCallback)>
 
-       function;
 
-   int min_args;
 
-   int max_args;
 
- };
 
- const Command ops[] = {
 
-     {"help", BindWith5Args(&GrpcTool::Help), 0, INT_MAX},
 
-     {"ls", BindWith5Args(&GrpcTool::ListServices), 1, 3},
 
-     {"list", BindWith5Args(&GrpcTool::ListServices), 1, 3},
 
-     {"call", BindWith5Args(&GrpcTool::CallMethod), 2, 3},
 
-     {"type", BindWith5Args(&GrpcTool::PrintType), 2, 2},
 
-     {"parse", BindWith5Args(&GrpcTool::ParseMessage), 2, 3},
 
-     {"totext", BindWith5Args(&GrpcTool::ToText), 2, 3},
 
-     {"tobinary", BindWith5Args(&GrpcTool::ToBinary), 2, 3},
 
-     {"tojson", BindWith5Args(&GrpcTool::ToJson), 2, 3},
 
- };
 
- void Usage(const std::string& msg) {
 
-   fprintf(
 
-       stderr,
 
-       "%s\n"
 
-       "  grpc_cli ls ...         ; List services\n"
 
-       "  grpc_cli call ...       ; Call method\n"
 
-       "  grpc_cli type ...       ; Print type\n"
 
-       "  grpc_cli parse ...      ; Parse message\n"
 
-       "  grpc_cli totext ...     ; Convert binary message to text\n"
 
-       "  grpc_cli tojson ...     ; Convert binary message to json\n"
 
-       "  grpc_cli tobinary ...   ; Convert text message to binary\n"
 
-       "  grpc_cli help ...       ; Print this message, or per-command usage\n"
 
-       "\n",
 
-       msg.c_str());
 
-   exit(1);
 
- }
 
- const Command* FindCommand(const std::string& name) {
 
-   for (int i = 0; i < (int)ArraySize(ops); i++) {
 
-     if (name == ops[i].command) {
 
-       return &ops[i];
 
-     }
 
-   }
 
-   return nullptr;
 
- }
 
- }  // namespace
 
- int GrpcToolMainLib(int argc, const char** argv, const CliCredentials& cred,
 
-                     const GrpcToolOutputCallback& callback) {
 
-   if (argc < 2) {
 
-     Usage("No command specified");
 
-   }
 
-   std::string command = argv[1];
 
-   argc -= 2;
 
-   argv += 2;
 
-   const Command* cmd = FindCommand(command);
 
-   if (cmd != nullptr) {
 
-     GrpcTool grpc_tool;
 
-     if (argc < cmd->min_args || argc > cmd->max_args) {
 
-       // Force the command to print its usage message
 
-       fprintf(stderr, "\nWrong number of arguments for %s\n", command.c_str());
 
-       grpc_tool.SetPrintCommandMode(1);
 
-       return cmd->function(&grpc_tool, -1, nullptr, cred, callback);
 
-     }
 
-     const bool ok = cmd->function(&grpc_tool, argc, argv, cred, callback);
 
-     return ok ? 0 : 1;
 
-   } else {
 
-     Usage("Invalid command '" + std::string(command.c_str()) + "'");
 
-   }
 
-   return 1;
 
- }
 
- GrpcTool::GrpcTool() : print_command_usage_(false), usage_exit_status_(0) {}
 
- void GrpcTool::CommandUsage(const std::string& usage) const {
 
-   if (print_command_usage_) {
 
-     fprintf(stderr, "\n%s%s\n", usage.c_str(),
 
-             (usage.empty() || usage[usage.size() - 1] != '\n') ? "\n" : "");
 
-     exit(usage_exit_status_);
 
-   }
 
- }
 
- bool GrpcTool::Help(int argc, const char** argv, const CliCredentials& cred,
 
-                     const GrpcToolOutputCallback& callback) {
 
-   CommandUsage(
 
-       "Print help\n"
 
-       "  grpc_cli help [subcommand]\n");
 
-   if (argc == 0) {
 
-     Usage("");
 
-   } else {
 
-     const Command* cmd = FindCommand(argv[0]);
 
-     if (cmd == nullptr) {
 
-       Usage("Unknown command '" + std::string(argv[0]) + "'");
 
-     }
 
-     SetPrintCommandMode(0);
 
-     cmd->function(this, -1, nullptr, cred, callback);
 
-   }
 
-   return true;
 
- }
 
- bool GrpcTool::ListServices(int argc, const char** argv,
 
-                             const CliCredentials& cred,
 
-                             const GrpcToolOutputCallback& callback) {
 
-   CommandUsage(
 
-       "List services\n"
 
-       "  grpc_cli ls <address> [<service>[/<method>]]\n"
 
-       "    <address>                ; host:port\n"
 
-       "    <service>                ; Exported service name\n"
 
-       "    <method>                 ; Method name\n"
 
-       "    --l                      ; Use a long listing format\n"
 
-       "    --outfile                ; Output filename (defaults to stdout)\n" +
 
-       cred.GetCredentialUsage());
 
-   std::string server_address(argv[0]);
 
-   std::shared_ptr<grpc::Channel> channel =
 
-       CreateCliChannel(server_address, cred);
 
-   grpc::ProtoReflectionDescriptorDatabase desc_db(channel);
 
-   grpc::protobuf::DescriptorPool desc_pool(&desc_db);
 
-   std::vector<std::string> service_list;
 
-   if (!desc_db.GetServices(&service_list)) {
 
-     fprintf(stderr, "Received an error when querying services endpoint.\n");
 
-     return false;
 
-   }
 
-   // If no service is specified, dump the list of services.
 
-   std::string output;
 
-   if (argc < 2) {
 
-     // List all services, if --l is passed, then include full description,
 
-     // otherwise include a summarized list only.
 
-     if (absl::GetFlag(FLAGS_l)) {
 
-       output = DescribeServiceList(service_list, desc_pool);
 
-     } else {
 
-       for (auto it = service_list.begin(); it != service_list.end(); it++) {
 
-         auto const& service = *it;
 
-         output.append(service);
 
-         output.append("\n");
 
-       }
 
-     }
 
-   } else {
 
-     std::string service_name;
 
-     std::string method_name;
 
-     std::stringstream ss(argv[1]);
 
-     // Remove leading slashes.
 
-     while (ss.peek() == '/') {
 
-       ss.get();
 
-     }
 
-     // Parse service and method names. Support the following patterns:
 
-     //   Service
 
-     //   Service Method
 
-     //   Service.Method
 
-     //   Service/Method
 
-     if (argc == 3) {
 
-       std::getline(ss, service_name, '/');
 
-       method_name = argv[2];
 
-     } else {
 
-       if (std::getline(ss, service_name, '/')) {
 
-         std::getline(ss, method_name);
 
-       }
 
-     }
 
-     const grpc::protobuf::ServiceDescriptor* service =
 
-         desc_pool.FindServiceByName(service_name);
 
-     if (service != nullptr) {
 
-       if (method_name.empty()) {
 
-         output = absl::GetFlag(FLAGS_l) ? DescribeService(service)
 
-                                         : SummarizeService(service);
 
-       } else {
 
-         method_name.insert(0, 1, '.');
 
-         method_name.insert(0, service_name);
 
-         const grpc::protobuf::MethodDescriptor* method =
 
-             desc_pool.FindMethodByName(method_name);
 
-         if (method != nullptr) {
 
-           output = absl::GetFlag(FLAGS_l) ? DescribeMethod(method)
 
-                                           : SummarizeMethod(method);
 
-         } else {
 
-           fprintf(stderr, "Method %s not found in service %s.\n",
 
-                   method_name.c_str(), service_name.c_str());
 
-           return false;
 
-         }
 
-       }
 
-     } else {
 
-       if (!method_name.empty()) {
 
-         fprintf(stderr, "Service %s not found.\n", service_name.c_str());
 
-         return false;
 
-       } else {
 
-         const grpc::protobuf::MethodDescriptor* method =
 
-             desc_pool.FindMethodByName(service_name);
 
-         if (method != nullptr) {
 
-           output = absl::GetFlag(FLAGS_l) ? DescribeMethod(method)
 
-                                           : SummarizeMethod(method);
 
-         } else {
 
-           fprintf(stderr, "Service or method %s not found.\n",
 
-                   service_name.c_str());
 
-           return false;
 
-         }
 
-       }
 
-     }
 
-   }
 
-   return callback(output);
 
- }
 
- bool GrpcTool::PrintType(int /*argc*/, const char** argv,
 
-                          const CliCredentials& cred,
 
-                          const GrpcToolOutputCallback& callback) {
 
-   CommandUsage(
 
-       "Print type\n"
 
-       "  grpc_cli type <address> <type>\n"
 
-       "    <address>                ; host:port\n"
 
-       "    <type>                   ; Protocol buffer type name\n" +
 
-       cred.GetCredentialUsage());
 
-   std::string server_address(argv[0]);
 
-   std::shared_ptr<grpc::Channel> channel =
 
-       CreateCliChannel(server_address, cred);
 
-   grpc::ProtoReflectionDescriptorDatabase desc_db(channel);
 
-   grpc::protobuf::DescriptorPool desc_pool(&desc_db);
 
-   std::string output;
 
-   const grpc::protobuf::Descriptor* descriptor =
 
-       desc_pool.FindMessageTypeByName(argv[1]);
 
-   if (descriptor != nullptr) {
 
-     output = descriptor->DebugString();
 
-   } else {
 
-     fprintf(stderr, "Type %s not found.\n", argv[1]);
 
-     return false;
 
-   }
 
-   return callback(output);
 
- }
 
- bool GrpcTool::CallMethod(int argc, const char** argv,
 
-                           const CliCredentials& cred,
 
-                           const GrpcToolOutputCallback& callback) {
 
-   CommandUsage(
 
-       "Call method\n"
 
-       "  grpc_cli call <address> <service>[.<method>] <request>\n"
 
-       "    <address>                ; host:port\n"
 
-       "    <service>                ; Exported service name\n"
 
-       "    <method>                 ; Method name\n"
 
-       "    <request>                ; Text protobuffer (overrides infile)\n"
 
-       "    --protofiles             ; Comma separated proto files used as a"
 
-       " fallback when parsing request/response\n"
 
-       "    --proto_path             ; The search path of proto files, valid"
 
-       " only when --protofiles is given\n"
 
-       "    --noremotedb             ; Don't attempt to use reflection service"
 
-       " at all\n"
 
-       "    --metadata               ; The metadata to be sent to the server\n"
 
-       "    --infile                 ; Input filename (defaults to stdin)\n"
 
-       "    --outfile                ; Output filename (defaults to stdout)\n"
 
-       "    --binary_input           ; Input in binary format\n"
 
-       "    --binary_output          ; Output in binary format\n"
 
-       "    --json_input             ; Input in json format\n"
 
-       "    --json_output            ; Output in json format\n"
 
-       "    --timeout                ; Specify timeout (in seconds), used to "
 
-       "set the deadline for RPCs. The default value of -1 means no "
 
-       "deadline has been set.\n" +
 
-       cred.GetCredentialUsage());
 
-   std::stringstream output_ss;
 
-   std::string request_text;
 
-   std::string server_address(argv[0]);
 
-   std::string method_name(argv[1]);
 
-   std::string formatted_method_name;
 
-   std::unique_ptr<ProtoFileParser> parser;
 
-   std::string serialized_request_proto;
 
-   CliArgs cli_args;
 
-   cli_args.timeout = absl::GetFlag(FLAGS_timeout);
 
-   bool print_mode = false;
 
-   std::shared_ptr<grpc::Channel> channel =
 
-       CreateCliChannel(server_address, cred);
 
-   if (!absl::GetFlag(FLAGS_binary_input) ||
 
-       !absl::GetFlag(FLAGS_binary_output)) {
 
-     parser = absl::make_unique<grpc::testing::ProtoFileParser>(
 
-         absl::GetFlag(FLAGS_remotedb) ? channel : nullptr,
 
-         absl::GetFlag(FLAGS_proto_path), absl::GetFlag(FLAGS_protofiles));
 
-     if (parser->HasError()) {
 
-       fprintf(
 
-           stderr,
 
-           "Failed to find remote reflection service and local proto files.\n");
 
-       return false;
 
-     }
 
-   }
 
-   if (absl::GetFlag(FLAGS_binary_input)) {
 
-     formatted_method_name = method_name;
 
-   } else {
 
-     formatted_method_name = parser->GetFormattedMethodName(method_name);
 
-     if (parser->HasError()) {
 
-       fprintf(stderr, "Failed to find method %s in proto files.\n",
 
-               method_name.c_str());
 
-     }
 
-   }
 
-   if (argc == 3) {
 
-     request_text = argv[2];
 
-   }
 
-   if (parser->IsStreaming(method_name, true /* is_request */)) {
 
-     std::istream* input_stream;
 
-     std::ifstream input_file;
 
-     if (absl::GetFlag(FLAGS_batch)) {
 
-       fprintf(stderr, "Batch mode for streaming RPC is not supported.\n");
 
-       return false;
 
-     }
 
-     std::multimap<std::string, std::string> client_metadata;
 
-     ParseMetadataFlag(&client_metadata);
 
-     PrintMetadata(client_metadata, "Sending client initial metadata:");
 
-     CliCall call(channel, formatted_method_name, client_metadata, cli_args);
 
-     if (absl::GetFlag(FLAGS_display_peer_address)) {
 
-       fprintf(stderr, "New call for method_name:%s has peer address:|%s|\n",
 
-               formatted_method_name.c_str(), call.peer().c_str());
 
-     }
 
-     if (absl::GetFlag(FLAGS_infile).empty()) {
 
-       if (isatty(fileno(stdin))) {
 
-         print_mode = true;
 
-         fprintf(stderr, "reading streaming request message from stdin...\n");
 
-       }
 
-       input_stream = &std::cin;
 
-     } else {
 
-       input_file.open(absl::GetFlag(FLAGS_infile),
 
-                       std::ios::in | std::ios::binary);
 
-       input_stream = &input_file;
 
-     }
 
-     gpr_mu parser_mu;
 
-     gpr_mu_init(&parser_mu);
 
-     std::thread read_thread(ReadResponse, &call, method_name, callback,
 
-                             parser.get(), &parser_mu, print_mode);
 
-     std::stringstream request_ss;
 
-     std::string line;
 
-     while (!request_text.empty() ||
 
-            (!input_stream->eof() && getline(*input_stream, line))) {
 
-       if (!request_text.empty()) {
 
-         if (absl::GetFlag(FLAGS_binary_input)) {
 
-           serialized_request_proto = request_text;
 
-           request_text.clear();
 
-         } else {
 
-           gpr_mu_lock(&parser_mu);
 
-           serialized_request_proto = parser->GetSerializedProtoFromMethod(
 
-               method_name, request_text, true /* is_request */,
 
-               absl::GetFlag(FLAGS_json_input));
 
-           request_text.clear();
 
-           if (parser->HasError()) {
 
-             if (print_mode) {
 
-               fprintf(stderr, "Failed to parse request.\n");
 
-             }
 
-             gpr_mu_unlock(&parser_mu);
 
-             continue;
 
-           }
 
-           gpr_mu_unlock(&parser_mu);
 
-         }
 
-         call.WriteAndWait(serialized_request_proto);
 
-         if (print_mode) {
 
-           fprintf(stderr, "Request sent.\n");
 
-         }
 
-       } else {
 
-         if (line.length() == 0) {
 
-           request_text = request_ss.str();
 
-           request_ss.str(std::string());
 
-           request_ss.clear();
 
-         } else {
 
-           request_ss << line << ' ';
 
-         }
 
-       }
 
-     }
 
-     if (input_file.is_open()) {
 
-       input_file.close();
 
-     }
 
-     call.WritesDoneAndWait();
 
-     read_thread.join();
 
-     gpr_mu_destroy(&parser_mu);
 
-     std::multimap<grpc::string_ref, grpc::string_ref> server_trailing_metadata;
 
-     Status status = call.Finish(&server_trailing_metadata);
 
-     PrintMetadata(server_trailing_metadata,
 
-                   "Received trailing metadata from server:");
 
-     if (status.ok()) {
 
-       fprintf(stderr, "Stream RPC succeeded with OK status\n");
 
-       return true;
 
-     } else {
 
-       fprintf(stderr, "Rpc failed with status code %d, error message: %s\n",
 
-               status.error_code(), status.error_message().c_str());
 
-       return false;
 
-     }
 
-   } else {  // parser->IsStreaming(method_name, true /* is_request */)
 
-     if (absl::GetFlag(FLAGS_batch)) {
 
-       if (parser->IsStreaming(method_name, false /* is_request */)) {
 
-         fprintf(stderr, "Batch mode for streaming RPC is not supported.\n");
 
-         return false;
 
-       }
 
-       std::istream* input_stream;
 
-       std::ifstream input_file;
 
-       if (absl::GetFlag(FLAGS_infile).empty()) {
 
-         if (isatty(fileno(stdin))) {
 
-           print_mode = true;
 
-           fprintf(stderr, "reading request messages from stdin...\n");
 
-         }
 
-         input_stream = &std::cin;
 
-       } else {
 
-         input_file.open(absl::GetFlag(FLAGS_infile),
 
-                         std::ios::in | std::ios::binary);
 
-         input_stream = &input_file;
 
-       }
 
-       std::multimap<std::string, std::string> client_metadata;
 
-       ParseMetadataFlag(&client_metadata);
 
-       if (print_mode) {
 
-         PrintMetadata(client_metadata, "Sending client initial metadata:");
 
-       }
 
-       std::stringstream request_ss;
 
-       std::string line;
 
-       while (!request_text.empty() ||
 
-              (!input_stream->eof() && getline(*input_stream, line))) {
 
-         if (!request_text.empty()) {
 
-           if (absl::GetFlag(FLAGS_binary_input)) {
 
-             serialized_request_proto = request_text;
 
-             request_text.clear();
 
-           } else {
 
-             serialized_request_proto = parser->GetSerializedProtoFromMethod(
 
-                 method_name, request_text, true /* is_request */,
 
-                 absl::GetFlag(FLAGS_json_input));
 
-             request_text.clear();
 
-             if (parser->HasError()) {
 
-               if (print_mode) {
 
-                 fprintf(stderr, "Failed to parse request.\n");
 
-               }
 
-               continue;
 
-             }
 
-           }
 
-           std::string serialized_response_proto;
 
-           std::multimap<grpc::string_ref, grpc::string_ref>
 
-               server_initial_metadata, server_trailing_metadata;
 
-           CliCall call(channel, formatted_method_name, client_metadata,
 
-                        cli_args);
 
-           if (absl::GetFlag(FLAGS_display_peer_address)) {
 
-             fprintf(stderr,
 
-                     "New call for method_name:%s has peer address:|%s|\n",
 
-                     formatted_method_name.c_str(), call.peer().c_str());
 
-           }
 
-           call.Write(serialized_request_proto);
 
-           call.WritesDone();
 
-           if (!call.Read(&serialized_response_proto,
 
-                          &server_initial_metadata)) {
 
-             fprintf(stderr, "Failed to read response.\n");
 
-           }
 
-           Status status = call.Finish(&server_trailing_metadata);
 
-           if (status.ok()) {
 
-             if (print_mode) {
 
-               fprintf(stderr, "Rpc succeeded with OK status.\n");
 
-               PrintMetadata(server_initial_metadata,
 
-                             "Received initial metadata from server:");
 
-               PrintMetadata(server_trailing_metadata,
 
-                             "Received trailing metadata from server:");
 
-             }
 
-             if (absl::GetFlag(FLAGS_binary_output)) {
 
-               if (!callback(serialized_response_proto)) {
 
-                 break;
 
-               }
 
-             } else {
 
-               std::string response_text = parser->GetFormattedStringFromMethod(
 
-                   method_name, serialized_response_proto,
 
-                   false /* is_request */, absl::GetFlag(FLAGS_json_output));
 
-               if (parser->HasError() && print_mode) {
 
-                 fprintf(stderr, "Failed to parse response.\n");
 
-               } else {
 
-                 if (!callback(response_text)) {
 
-                   break;
 
-                 }
 
-               }
 
-             }
 
-           } else {
 
-             if (print_mode) {
 
-               fprintf(stderr,
 
-                       "Rpc failed with status code %d, error message: %s\n",
 
-                       status.error_code(), status.error_message().c_str());
 
-             }
 
-           }
 
-         } else {
 
-           if (line.length() == 0) {
 
-             request_text = request_ss.str();
 
-             request_ss.str(std::string());
 
-             request_ss.clear();
 
-           } else {
 
-             request_ss << line << ' ';
 
-           }
 
-         }
 
-       }
 
-       if (input_file.is_open()) {
 
-         input_file.close();
 
-       }
 
-       return true;
 
-     }
 
-     if (argc == 3) {
 
-       if (!absl::GetFlag(FLAGS_infile).empty()) {
 
-         fprintf(stderr, "warning: request given in argv, ignoring --infile\n");
 
-       }
 
-     } else {
 
-       std::stringstream input_stream;
 
-       if (absl::GetFlag(FLAGS_infile).empty()) {
 
-         if (isatty(fileno(stdin))) {
 
-           fprintf(stderr, "reading request message from stdin...\n");
 
-         }
 
-         input_stream << std::cin.rdbuf();
 
-       } else {
 
-         std::ifstream input_file(absl::GetFlag(FLAGS_infile),
 
-                                  std::ios::in | std::ios::binary);
 
-         input_stream << input_file.rdbuf();
 
-         input_file.close();
 
-       }
 
-       request_text = input_stream.str();
 
-     }
 
-     if (absl::GetFlag(FLAGS_binary_input)) {
 
-       serialized_request_proto = request_text;
 
-     } else {
 
-       serialized_request_proto = parser->GetSerializedProtoFromMethod(
 
-           method_name, request_text, true /* is_request */,
 
-           absl::GetFlag(FLAGS_json_input));
 
-       if (parser->HasError()) {
 
-         fprintf(stderr, "Failed to parse request.\n");
 
-         return false;
 
-       }
 
-     }
 
-     fprintf(stderr, "connecting to %s\n", server_address.c_str());
 
-     std::string serialized_response_proto;
 
-     std::multimap<std::string, std::string> client_metadata;
 
-     std::multimap<grpc::string_ref, grpc::string_ref> server_initial_metadata,
 
-         server_trailing_metadata;
 
-     ParseMetadataFlag(&client_metadata);
 
-     PrintMetadata(client_metadata, "Sending client initial metadata:");
 
-     CliCall call(channel, formatted_method_name, client_metadata, cli_args);
 
-     if (absl::GetFlag(FLAGS_display_peer_address)) {
 
-       fprintf(stderr, "New call for method_name:%s has peer address:|%s|\n",
 
-               formatted_method_name.c_str(), call.peer().c_str());
 
-     }
 
-     call.Write(serialized_request_proto);
 
-     call.WritesDone();
 
-     for (bool receive_initial_metadata = true; call.Read(
 
-              &serialized_response_proto,
 
-              receive_initial_metadata ? &server_initial_metadata : nullptr);
 
-          receive_initial_metadata = false) {
 
-       if (!absl::GetFlag(FLAGS_binary_output)) {
 
-         serialized_response_proto = parser->GetFormattedStringFromMethod(
 
-             method_name, serialized_response_proto, false /* is_request */,
 
-             absl::GetFlag(FLAGS_json_output));
 
-         if (parser->HasError()) {
 
-           fprintf(stderr, "Failed to parse response.\n");
 
-           return false;
 
-         }
 
-       }
 
-       if (receive_initial_metadata) {
 
-         PrintMetadata(server_initial_metadata,
 
-                       "Received initial metadata from server:");
 
-       }
 
-       if (!callback(serialized_response_proto)) {
 
-         return false;
 
-       }
 
-     }
 
-     Status status = call.Finish(&server_trailing_metadata);
 
-     PrintMetadata(server_trailing_metadata,
 
-                   "Received trailing metadata from server:");
 
-     if (status.ok()) {
 
-       fprintf(stderr, "Rpc succeeded with OK status\n");
 
-       return true;
 
-     } else {
 
-       fprintf(stderr, "Rpc failed with status code %d, error message: %s\n",
 
-               status.error_code(), status.error_message().c_str());
 
-       return false;
 
-     }
 
-   }
 
-   GPR_UNREACHABLE_CODE(return false);
 
- }
 
- bool GrpcTool::ParseMessage(int argc, const char** argv,
 
-                             const CliCredentials& cred,
 
-                             const GrpcToolOutputCallback& callback) {
 
-   CommandUsage(
 
-       "Parse message\n"
 
-       "  grpc_cli parse <address> <type> [<message>]\n"
 
-       "    <address>                ; host:port\n"
 
-       "    <type>                   ; Protocol buffer type name\n"
 
-       "    <message>                ; Text protobuffer (overrides --infile)\n"
 
-       "    --protofiles             ; Comma separated proto files used as a"
 
-       " fallback when parsing request/response\n"
 
-       "    --proto_path             ; The search path of proto files, valid"
 
-       " only when --protofiles is given\n"
 
-       "    --noremotedb             ; Don't attempt to use reflection service"
 
-       " at all\n"
 
-       "    --infile                 ; Input filename (defaults to stdin)\n"
 
-       "    --outfile                ; Output filename (defaults to stdout)\n"
 
-       "    --binary_input           ; Input in binary format\n"
 
-       "    --binary_output          ; Output in binary format\n"
 
-       "    --json_input             ; Input in json format\n"
 
-       "    --json_output            ; Output in json format\n" +
 
-       cred.GetCredentialUsage());
 
-   std::stringstream output_ss;
 
-   std::string message_text;
 
-   std::string server_address(argv[0]);
 
-   std::string type_name(argv[1]);
 
-   std::unique_ptr<grpc::testing::ProtoFileParser> parser;
 
-   std::string serialized_request_proto;
 
-   if (argc == 3) {
 
-     message_text = argv[2];
 
-     if (!absl::GetFlag(FLAGS_infile).empty()) {
 
-       fprintf(stderr, "warning: message given in argv, ignoring --infile.\n");
 
-     }
 
-   } else {
 
-     std::stringstream input_stream;
 
-     if (absl::GetFlag(FLAGS_infile).empty()) {
 
-       if (isatty(fileno(stdin))) {
 
-         fprintf(stderr, "reading request message from stdin...\n");
 
-       }
 
-       input_stream << std::cin.rdbuf();
 
-     } else {
 
-       std::ifstream input_file(absl::GetFlag(FLAGS_infile),
 
-                                std::ios::in | std::ios::binary);
 
-       input_stream << input_file.rdbuf();
 
-       input_file.close();
 
-     }
 
-     message_text = input_stream.str();
 
-   }
 
-   if (!absl::GetFlag(FLAGS_binary_input) ||
 
-       !absl::GetFlag(FLAGS_binary_output)) {
 
-     std::shared_ptr<grpc::Channel> channel =
 
-         CreateCliChannel(server_address, cred);
 
-     parser = absl::make_unique<grpc::testing::ProtoFileParser>(
 
-         absl::GetFlag(FLAGS_remotedb) ? channel : nullptr,
 
-         absl::GetFlag(FLAGS_proto_path), absl::GetFlag(FLAGS_protofiles));
 
-     if (parser->HasError()) {
 
-       fprintf(
 
-           stderr,
 
-           "Failed to find remote reflection service and local proto files.\n");
 
-       return false;
 
-     }
 
-   }
 
-   if (absl::GetFlag(FLAGS_binary_input)) {
 
-     serialized_request_proto = message_text;
 
-   } else {
 
-     serialized_request_proto = parser->GetSerializedProtoFromMessageType(
 
-         type_name, message_text, absl::GetFlag(FLAGS_json_input));
 
-     if (parser->HasError()) {
 
-       fprintf(stderr, "Failed to serialize the message.\n");
 
-       return false;
 
-     }
 
-   }
 
-   if (absl::GetFlag(FLAGS_binary_output)) {
 
-     output_ss << serialized_request_proto;
 
-   } else {
 
-     std::string output_text;
 
-     output_text = parser->GetFormattedStringFromMessageType(
 
-         type_name, serialized_request_proto, absl::GetFlag(FLAGS_json_output));
 
-     if (parser->HasError()) {
 
-       fprintf(stderr, "Failed to deserialize the message.\n");
 
-       return false;
 
-     }
 
-     output_ss << output_text << std::endl;
 
-   }
 
-   return callback(output_ss.str());
 
- }
 
- bool GrpcTool::ToText(int argc, const char** argv, const CliCredentials& cred,
 
-                       const GrpcToolOutputCallback& callback) {
 
-   CommandUsage(
 
-       "Convert binary message to text\n"
 
-       "  grpc_cli totext <protofiles> <type>\n"
 
-       "    <protofiles>             ; Comma separated list of proto files\n"
 
-       "    <type>                   ; Protocol buffer type name\n"
 
-       "    --proto_path             ; The search path of proto files\n"
 
-       "    --infile                 ; Input filename (defaults to stdin)\n"
 
-       "    --outfile                ; Output filename (defaults to stdout)\n");
 
-   absl::SetFlag(&FLAGS_protofiles, argv[0]);
 
-   absl::SetFlag(&FLAGS_remotedb, false);
 
-   absl::SetFlag(&FLAGS_binary_input, true);
 
-   absl::SetFlag(&FLAGS_binary_output, false);
 
-   return ParseMessage(argc, argv, cred, callback);
 
- }
 
- bool GrpcTool::ToJson(int argc, const char** argv, const CliCredentials& cred,
 
-                       const GrpcToolOutputCallback& callback) {
 
-   CommandUsage(
 
-       "Convert binary message to json\n"
 
-       "  grpc_cli tojson <protofiles> <type>\n"
 
-       "    <protofiles>             ; Comma separated list of proto files\n"
 
-       "    <type>                   ; Protocol buffer type name\n"
 
-       "    --proto_path             ; The search path of proto files\n"
 
-       "    --infile                 ; Input filename (defaults to stdin)\n"
 
-       "    --outfile                ; Output filename (defaults to stdout)\n");
 
-   absl::SetFlag(&FLAGS_protofiles, argv[0]);
 
-   absl::SetFlag(&FLAGS_remotedb, false);
 
-   absl::SetFlag(&FLAGS_binary_input, true);
 
-   absl::SetFlag(&FLAGS_binary_output, false);
 
-   absl::SetFlag(&FLAGS_json_output, true);
 
-   return ParseMessage(argc, argv, cred, callback);
 
- }
 
- bool GrpcTool::ToBinary(int argc, const char** argv, const CliCredentials& cred,
 
-                         const GrpcToolOutputCallback& callback) {
 
-   CommandUsage(
 
-       "Convert text message to binary\n"
 
-       "  grpc_cli tobinary <protofiles> <type> [<message>]\n"
 
-       "    <protofiles>             ; Comma separated list of proto files\n"
 
-       "    <type>                   ; Protocol buffer type name\n"
 
-       "    --proto_path             ; The search path of proto files\n"
 
-       "    --infile                 ; Input filename (defaults to stdin)\n"
 
-       "    --outfile                ; Output filename (defaults to stdout)\n");
 
-   absl::SetFlag(&FLAGS_protofiles, argv[0]);
 
-   absl::SetFlag(&FLAGS_remotedb, false);
 
-   absl::SetFlag(&FLAGS_binary_input, false);
 
-   absl::SetFlag(&FLAGS_binary_output, true);
 
-   return ParseMessage(argc, argv, cred, callback);
 
- }
 
- }  // namespace testing
 
- }  // namespace grpc
 
 
  |