|  | @@ -34,18 +34,21 @@
 | 
	
		
			
				|  |  |  /*
 | 
	
		
			
				|  |  |    A command line tool to talk to a grpc server.
 | 
	
		
			
				|  |  |    Example of talking to grpc interop server:
 | 
	
		
			
				|  |  | -  grpc_cli call localhost:50051 UnaryCall src/proto/grpc/testing/test.proto \
 | 
	
		
			
				|  |  | -    "response_size:10"  --enable_ssl=false
 | 
	
		
			
				|  |  | +  grpc_cli call localhost:50051 UnaryCall "response_size:10" \
 | 
	
		
			
				|  |  | +      --protofiles=src/proto/grpc/testing/test.proto --enable_ssl=false
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    Options:
 | 
	
		
			
				|  |  | -    1. --proto_path, if your proto file is not under current working directory,
 | 
	
		
			
				|  |  | +    1. --protofiles, use this flag to provide a proto file if the server does
 | 
	
		
			
				|  |  | +       does not have the reflection service.
 | 
	
		
			
				|  |  | +    2. --proto_path, if your proto file is not under current working directory,
 | 
	
		
			
				|  |  |         use this flag to provide a search root. It should work similar to the
 | 
	
		
			
				|  |  | -       counterpart in protoc.
 | 
	
		
			
				|  |  | -    2. --metadata specifies metadata to be sent to the server, such as:
 | 
	
		
			
				|  |  | +       counterpart in protoc. This option is valid only when protofiles is
 | 
	
		
			
				|  |  | +       provided.
 | 
	
		
			
				|  |  | +    3. --metadata specifies metadata to be sent to the server, such as:
 | 
	
		
			
				|  |  |         --metadata="MyHeaderKey1:Value1:MyHeaderKey2:Value2"
 | 
	
		
			
				|  |  | -    3. --enable_ssl, whether to use tls.
 | 
	
		
			
				|  |  | -    4. --use_auth, if set to true, attach a GoogleDefaultCredentials to the call
 | 
	
		
			
				|  |  | -    3. --input_binary_file, a file containing the serialized request. The file
 | 
	
		
			
				|  |  | +    4. --enable_ssl, whether to use tls.
 | 
	
		
			
				|  |  | +    5. --use_auth, if set to true, attach a GoogleDefaultCredentials to the call
 | 
	
		
			
				|  |  | +    6. --input_binary_file, a file containing the serialized request. The file
 | 
	
		
			
				|  |  |         can be generated by calling something like:
 | 
	
		
			
				|  |  |         protoc --proto_path=src/proto/grpc/testing/ \
 | 
	
		
			
				|  |  |           --encode=grpc.testing.SimpleRequest \
 | 
	
	
		
			
				|  | @@ -53,7 +56,7 @@
 | 
	
		
			
				|  |  |           < input.txt > input.bin
 | 
	
		
			
				|  |  |         If this is used and no proto file is provided in the argument list, the
 | 
	
		
			
				|  |  |         method string has to be exact in the form of /package.service/method.
 | 
	
		
			
				|  |  | -    4. --output_binary_file, a file to write binary format response into, it can
 | 
	
		
			
				|  |  | +    7. --output_binary_file, a file to write binary format response into, it can
 | 
	
		
			
				|  |  |         be later decoded using protoc:
 | 
	
		
			
				|  |  |         protoc --proto_path=src/proto/grpc/testing/ \
 | 
	
		
			
				|  |  |         --decode=grpc.testing.SimpleResponse \
 | 
	
	
		
			
				|  | @@ -61,6 +64,7 @@
 | 
	
		
			
				|  |  |         < output.bin > output.txt
 | 
	
		
			
				|  |  |  */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#include <unistd.h>
 | 
	
		
			
				|  |  |  #include <fstream>
 | 
	
		
			
				|  |  |  #include <iostream>
 | 
	
		
			
				|  |  |  #include <sstream>
 | 
	
	
		
			
				|  | @@ -86,6 +90,8 @@ DEFINE_string(output_binary_file, "",
 | 
	
		
			
				|  |  |  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.");
 | 
	
		
			
				|  |  | +// TODO(zyc): support a list of input proto files
 | 
	
		
			
				|  |  | +DEFINE_string(protofiles, "", "Name of the proto file.");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void ParseMetadataFlag(
 | 
	
		
			
				|  |  |      std::multimap<grpc::string, grpc::string>* client_metadata) {
 | 
	
	
		
			
				|  | @@ -129,35 +135,61 @@ void PrintMetadata(const T& m, const grpc::string& message) {
 | 
	
		
			
				|  |  |  int main(int argc, char** argv) {
 | 
	
		
			
				|  |  |    grpc::testing::InitTest(&argc, &argv, true);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  if (argc < 4 || argc == 5 || grpc::string(argv[1]) != "call") {
 | 
	
		
			
				|  |  | +  if (argc < 4 || grpc::string(argv[1]) != "call") {
 | 
	
		
			
				|  |  |      std::cout << "Usage: grpc_cli call server_host:port method_name "
 | 
	
		
			
				|  |  |                << "[proto file] [text format request] [<options>]" << std::endl;
 | 
	
		
			
				|  |  | +    return 1;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  grpc::string file_name;
 | 
	
		
			
				|  |  |    grpc::string request_text;
 | 
	
		
			
				|  |  |    grpc::string server_address(argv[2]);
 | 
	
		
			
				|  |  |    grpc::string method_name(argv[3]);
 | 
	
		
			
				|  |  |    std::unique_ptr<grpc::testing::ProtoFileParser> parser;
 | 
	
		
			
				|  |  |    grpc::string serialized_request_proto;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  if (argc == 6) {
 | 
	
		
			
				|  |  | -    file_name = argv[4];
 | 
	
		
			
				|  |  | -    // TODO(yangg) read from stdin as well?
 | 
	
		
			
				|  |  | -    request_text = argv[5];
 | 
	
		
			
				|  |  | +  if (argc == 5) {
 | 
	
		
			
				|  |  | +    request_text = argv[4];
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  std::shared_ptr<grpc::ChannelCredentials> creds;
 | 
	
		
			
				|  |  | +  if (!FLAGS_enable_ssl) {
 | 
	
		
			
				|  |  | +    creds = grpc::InsecureChannelCredentials();
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    if (FLAGS_use_auth) {
 | 
	
		
			
				|  |  | +      creds = grpc::GoogleDefaultCredentials();
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | +  std::shared_ptr<grpc::Channel> channel =
 | 
	
		
			
				|  |  | +      grpc::CreateChannel(server_address, creds);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (request_text.empty() && FLAGS_input_binary_file.empty()) {
 | 
	
		
			
				|  |  | -    std::cout << "Missing input. Use text format input or "
 | 
	
		
			
				|  |  | -              << "--input_binary_file for serialized request" << std::endl;
 | 
	
		
			
				|  |  | -    return 1;
 | 
	
		
			
				|  |  | -  } else if (!request_text.empty()) {
 | 
	
		
			
				|  |  | -    parser.reset(new grpc::testing::ProtoFileParser(FLAGS_proto_path, file_name,
 | 
	
		
			
				|  |  | -                                                    method_name));
 | 
	
		
			
				|  |  | +    if (isatty(STDIN_FILENO)) {
 | 
	
		
			
				|  |  | +      std::cout << "reading request message from stdin..." << std::endl;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    std::stringstream input_stream;
 | 
	
		
			
				|  |  | +    input_stream << std::cin.rdbuf();
 | 
	
		
			
				|  |  | +    request_text = input_stream.str();
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (!request_text.empty()) {
 | 
	
		
			
				|  |  | +    if (!FLAGS_protofiles.empty()) {
 | 
	
		
			
				|  |  | +      parser.reset(new grpc::testing::ProtoFileParser(
 | 
	
		
			
				|  |  | +          FLAGS_proto_path, FLAGS_protofiles, method_name));
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      parser.reset(new grpc::testing::ProtoFileParser(channel, method_name));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      method_name = parser->GetFullMethodName();
 | 
	
		
			
				|  |  |      if (parser->HasError()) {
 | 
	
		
			
				|  |  |        return 1;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (!FLAGS_input_binary_file.empty()) {
 | 
	
		
			
				|  |  | +      std::cout
 | 
	
		
			
				|  |  | +          << "warning: request given in argv, ignoring --input_binary_file"
 | 
	
		
			
				|  |  | +          << std::endl;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (parser) {
 | 
	
	
		
			
				|  | @@ -175,19 +207,6 @@ int main(int argc, char** argv) {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    std::cout << "connecting to " << server_address << std::endl;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  std::shared_ptr<grpc::ChannelCredentials> creds;
 | 
	
		
			
				|  |  | -  if (!FLAGS_enable_ssl) {
 | 
	
		
			
				|  |  | -    creds = grpc::InsecureChannelCredentials();
 | 
	
		
			
				|  |  | -  } else {
 | 
	
		
			
				|  |  | -    if (FLAGS_use_auth) {
 | 
	
		
			
				|  |  | -      creds = grpc::GoogleDefaultCredentials();
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  std::shared_ptr<grpc::Channel> channel =
 | 
	
		
			
				|  |  | -      grpc::CreateChannel(server_address, creds);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    grpc::string serialized_response_proto;
 | 
	
		
			
				|  |  |    std::multimap<grpc::string, grpc::string> client_metadata;
 | 
	
		
			
				|  |  |    std::multimap<grpc::string_ref, grpc::string_ref> server_initial_metadata,
 | 
	
	
		
			
				|  | @@ -219,7 +238,7 @@ int main(int argc, char** argv) {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  |      std::cout << "Rpc failed with status code " << s.error_code()
 | 
	
		
			
				|  |  | -              << " error message " << s.error_message() << std::endl;
 | 
	
		
			
				|  |  | +              << ", error message: " << s.error_message() << std::endl;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    return 0;
 |