| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498 | 
							- /*
 
-  *
 
-  * Copyright 2016, Google Inc.
 
-  * All rights reserved.
 
-  *
 
-  * Redistribution and use in source and binary forms, with or without
 
-  * modification, are permitted provided that the following conditions are
 
-  * met:
 
-  *
 
-  *     * Redistributions of source code must retain the above copyright
 
-  * notice, this list of conditions and the following disclaimer.
 
-  *     * Redistributions in binary form must reproduce the above
 
-  * copyright notice, this list of conditions and the following disclaimer
 
-  * in the documentation and/or other materials provided with the
 
-  * distribution.
 
-  *     * Neither the name of Google Inc. nor the names of its
 
-  * contributors may be used to endorse or promote products derived from
 
-  * this software without specific prior written permission.
 
-  *
 
-  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
-  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
-  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
-  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
-  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
-  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
-  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
-  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
-  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
-  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
-  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-  *
 
-  */
 
- #include "test/cpp/util/grpc_tool.h"
 
- #include <unistd.h>
 
- #include <fstream>
 
- #include <iostream>
 
- #include <memory>
 
- #include <sstream>
 
- #include <string>
 
- #include <gflags/gflags.h>
 
- #include <grpc++/channel.h>
 
- #include <grpc++/create_channel.h>
 
- #include <grpc++/grpc++.h>
 
- #include <grpc++/security/credentials.h>
 
- #include <grpc++/support/string_ref.h>
 
- #include <grpc/grpc.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"
 
- #include "test/cpp/util/test_config.h"
 
- namespace grpc {
 
- namespace testing {
 
- DEFINE_bool(l, false, "Use a long listing format");
 
- DEFINE_bool(remotedb, true, "Use server types to parse and format messages");
 
- DEFINE_string(metadata, "",
 
-               "Metadata to send to server, in the form of key1:val1:key2:val2");
 
- DEFINE_string(proto_path, ".", "Path to look for the proto file.");
 
- DEFINE_string(protofiles, "", "Name of the proto file.");
 
- DEFINE_bool(binary_input, false, "Input in binary format");
 
- DEFINE_bool(binary_output, false, "Output in binary format");
 
- DEFINE_string(infile, "", "Input file (default is stdin)");
 
- namespace {
 
- class GrpcTool {
 
-  public:
 
-   explicit GrpcTool();
 
-   virtual ~GrpcTool() {}
 
-   bool Help(int argc, const char** argv, const CliCredentials& cred,
 
-             GrpcToolOutputCallback callback);
 
-   bool CallMethod(int argc, const char** argv, const CliCredentials& cred,
 
-                   GrpcToolOutputCallback callback);
 
-   bool ListServices(int argc, const char** argv, const CliCredentials& cred,
 
-                     GrpcToolOutputCallback callback);
 
-   bool PrintType(int argc, const char** argv, const CliCredentials& cred,
 
-                  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, GrpcToolOutputCallback
 
-   // callback);
 
-   // bool ToText(int argc, const char** argv, GrpcToolOutputCallback callback);
 
-   // bool ToBinary(int argc, const char** argv, GrpcToolOutputCallback
 
-   // callback);
 
-   void SetPrintCommandMode(int exit_status) {
 
-     print_command_usage_ = true;
 
-     usage_exit_status_ = exit_status;
 
-   }
 
-  private:
 
-   void CommandUsage(const grpc::string& usage) const;
 
-   bool print_command_usage_;
 
-   int usage_exit_status_;
 
-   const grpc::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<grpc::string, grpc::string>* client_metadata) {
 
-   if (FLAGS_metadata.empty()) {
 
-     return;
 
-   }
 
-   std::vector<grpc::string> fields;
 
-   const char* delim = ":";
 
-   size_t cur, next = -1;
 
-   do {
 
-     cur = next + 1;
 
-     next = FLAGS_metadata.find_first_of(delim, cur);
 
-     fields.push_back(FLAGS_metadata.substr(cur, next - cur));
 
-   } while (next != grpc::string::npos);
 
-   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<grpc::string, grpc::string>(fields[i], fields[i + 1]));
 
-   }
 
- }
 
- template <typename T>
 
- void PrintMetadata(const T& m, const grpc::string& message) {
 
-   if (m.empty()) {
 
-     return;
 
-   }
 
-   fprintf(stderr, "%s\n", message.c_str());
 
-   grpc::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());
 
-   }
 
- }
 
- 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},
 
- };
 
- void Usage(const grpc::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 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 grpc::string& name) {
 
-   for (int i = 0; i < (int)ArraySize(ops); i++) {
 
-     if (name == ops[i].command) {
 
-       return &ops[i];
 
-     }
 
-   }
 
-   return NULL;
 
- }
 
- }  // namespace
 
- int GrpcToolMainLib(int argc, const char** argv, const CliCredentials& cred,
 
-                     GrpcToolOutputCallback callback) {
 
-   if (argc < 2) {
 
-     Usage("No command specified");
 
-   }
 
-   grpc::string command = argv[1];
 
-   argc -= 2;
 
-   argv += 2;
 
-   const Command* cmd = FindCommand(command);
 
-   if (cmd != NULL) {
 
-     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, NULL, cred, callback);
 
-     }
 
-     const bool ok = cmd->function(&grpc_tool, argc, argv, cred, callback);
 
-     return ok ? 0 : 1;
 
-   } else {
 
-     Usage("Invalid command '" + grpc::string(command.c_str()) + "'");
 
-   }
 
-   return 1;
 
- }
 
- GrpcTool::GrpcTool() : print_command_usage_(false), usage_exit_status_(0) {}
 
- void GrpcTool::CommandUsage(const grpc::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,
 
-                     GrpcToolOutputCallback callback) {
 
-   CommandUsage(
 
-       "Print help\n"
 
-       "  grpc_cli help [subcommand]\n");
 
-   if (argc == 0) {
 
-     Usage("");
 
-   } else {
 
-     const Command* cmd = FindCommand(argv[0]);
 
-     if (cmd == NULL) {
 
-       Usage("Unknown command '" + grpc::string(argv[0]) + "'");
 
-     }
 
-     SetPrintCommandMode(0);
 
-     cmd->function(this, -1, NULL, cred, callback);
 
-   }
 
-   return true;
 
- }
 
- bool GrpcTool::ListServices(int argc, const char** argv,
 
-                             const CliCredentials& cred,
 
-                             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());
 
-   grpc::string server_address(argv[0]);
 
-   std::shared_ptr<grpc::Channel> channel =
 
-       grpc::CreateChannel(server_address, cred.GetCredentials());
 
-   grpc::ProtoReflectionDescriptorDatabase desc_db(channel);
 
-   grpc::protobuf::DescriptorPool desc_pool(&desc_db);
 
-   std::vector<grpc::string> service_list;
 
-   if (!desc_db.GetServices(&service_list)) {
 
-     return false;
 
-   }
 
-   // If no service is specified, dump the list of services.
 
-   grpc::string output;
 
-   if (argc < 2) {
 
-     // List all services, if --l is passed, then include full description,
 
-     // otherwise include a summarized list only.
 
-     if (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 {
 
-     grpc::string service_name;
 
-     grpc::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 = 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 = 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 = 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,
 
-                          GrpcToolOutputCallback callback) {
 
-   CommandUsage(
 
-       "Print type\n"
 
-       "  grpc_cli type <address> <type>\n"
 
-       "    <address>                ; host:port\n"
 
-       "    <type>                   ; Protocol buffer type name\n" +
 
-       cred.GetCredentialUsage());
 
-   grpc::string server_address(argv[0]);
 
-   std::shared_ptr<grpc::Channel> channel =
 
-       grpc::CreateChannel(server_address, cred.GetCredentials());
 
-   grpc::ProtoReflectionDescriptorDatabase desc_db(channel);
 
-   grpc::protobuf::DescriptorPool desc_pool(&desc_db);
 
-   grpc::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,
 
-                           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"
 
-       "    --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" +
 
-       cred.GetCredentialUsage());
 
-   std::stringstream output_ss;
 
-   grpc::string request_text;
 
-   grpc::string server_address(argv[0]);
 
-   grpc::string method_name(argv[1]);
 
-   std::unique_ptr<grpc::testing::ProtoFileParser> parser;
 
-   grpc::string serialized_request_proto;
 
-   if (argc == 3) {
 
-     request_text = argv[2];
 
-     if (!FLAGS_infile.empty()) {
 
-       fprintf(stderr, "warning: request given in argv, ignoring --infile\n");
 
-     }
 
-   } else {
 
-     std::stringstream input_stream;
 
-     if (FLAGS_infile.empty()) {
 
-       if (isatty(STDIN_FILENO)) {
 
-         fprintf(stderr, "reading request message from stdin...\n");
 
-       }
 
-       input_stream << std::cin.rdbuf();
 
-     } else {
 
-       std::ifstream input_file(FLAGS_infile, std::ios::in | std::ios::binary);
 
-       input_stream << input_file.rdbuf();
 
-       input_file.close();
 
-     }
 
-     request_text = input_stream.str();
 
-   }
 
-   std::shared_ptr<grpc::Channel> channel =
 
-       grpc::CreateChannel(server_address, cred.GetCredentials());
 
-   if (!FLAGS_binary_input || !FLAGS_binary_output) {
 
-     parser.reset(
 
-         new grpc::testing::ProtoFileParser(FLAGS_remotedb ? channel : nullptr,
 
-                                            FLAGS_proto_path, FLAGS_protofiles));
 
-     if (parser->HasError()) {
 
-       return false;
 
-     }
 
-   }
 
-   if (FLAGS_binary_input) {
 
-     serialized_request_proto = request_text;
 
-   } else {
 
-     serialized_request_proto = parser->GetSerializedProtoFromMethod(
 
-         method_name, request_text, true /* is_request */);
 
-     if (parser->HasError()) {
 
-       return false;
 
-     }
 
-   }
 
-   fprintf(stderr, "connecting to %s\n", server_address.c_str());
 
-   grpc::string serialized_response_proto;
 
-   std::multimap<grpc::string, grpc::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:");
 
-   grpc::Status status = grpc::testing::CliCall::Call(
 
-       channel, parser->GetFormatedMethodName(method_name),
 
-       serialized_request_proto, &serialized_response_proto, client_metadata,
 
-       &server_initial_metadata, &server_trailing_metadata);
 
-   PrintMetadata(server_initial_metadata,
 
-                 "Received initial metadata from server:");
 
-   PrintMetadata(server_trailing_metadata,
 
-                 "Received trailing metadata from server:");
 
-   if (status.ok()) {
 
-     fprintf(stderr, "Rpc succeeded with OK status\n");
 
-     if (FLAGS_binary_output) {
 
-       output_ss << serialized_response_proto;
 
-     } else {
 
-       grpc::string response_text = parser->GetTextFormatFromMethod(
 
-           method_name, serialized_response_proto, false /* is_request */);
 
-       if (parser->HasError()) {
 
-         return false;
 
-       }
 
-       output_ss << "Response: \n " << response_text << std::endl;
 
-     }
 
-   } else {
 
-     fprintf(stderr, "Rpc failed with status code %d, error message: %s\n",
 
-             status.error_code(), status.error_message().c_str());
 
-   }
 
-   return callback(output_ss.str());
 
- }
 
- }  // namespace testing
 
- }  // namespace grpc
 
 
  |