1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <iostream>
18
19 #include <android-base/logging.h>
20 #include <android-base/strings.h>
21
22 #include "common/libs/utils/result.h"
23 #include "host/libs/config/cuttlefish_config.h"
24 #include "host/libs/control_env/grpc_service_handler.h"
25
26 namespace cuttlefish {
27 namespace {
28
29 constexpr char kCvdEnvHelpMessage[] =
30 "cvd env: cuttlefish environment controller\n"
31 " e.g. Wmediumd & OpenWRT for Wifi, GNSS for geolocation\n"
32 "\n"
33 "Please visit following link for the more information.\n"
34 "https://source.android.com/docs/setup/create/"
35 "cuttlefish-control-environment\n"
36 "\n"
37 "Basic usage: cvd [SELECTOR_OPTIONS] env [SUBCOMMAND] [ARGS]\n"
38 "\n"
39 "Subcommands:\n"
40 " ls: List available services or methods\n"
41 " Get a list of all services:\n"
42 " Usage: cvd [SELECTOR_OPTIONS] env ls\n"
43 " Get a list of all methods for a service:\n"
44 " Usage: cvd [SELECTOR_OPTIONS] env ls [SERVICE_NAME]\n"
45 " Get detailed information like request or response message types of a "
46 "method:\n"
47 " Usage: cvd [SELECTOR_OPTIONS] env ls [SERVICE_NAME] [METHOD_NAME]\n"
48 " call: Send RPC request to make changes to the environment\n"
49 " Usage: cvd [SELECTOR_OPTIONS] env call [SERVICE_NAME] [METHOD_NAME] "
50 "[JSON_FORMATTED_PROTO]\n"
51 " type: Get detailed information on message types\n"
52 " Usage: cvd [SELECTOR_OPTIONS] env type [SERVICE_NAME] [TYPE_NAME]\n"
53 "\n"
54 "Arguments:\n"
55 " SERVICE_NAME : gRPC service name\n"
56 " METHOD_NAME : method name in given service\n"
57 " TYPE_NAME : Protobuf message type name including request or "
58 "response messages\n"
59 " JSON_FORMATTED_PROTO : Protobuf message data with JSON format\n"
60 "\n"
61 "* \"cvd [SELECTOR_OPTIONS] env\" can be replaced with: \"cvd_internal_env "
62 "[INTERNAL_DEVICE_NAME]\"\n";
63
64 constexpr char kServiceControlEnvProxy[] = "ControlEnvProxyService";
65
ContainHelpOption(int argc,char ** argv)66 bool ContainHelpOption(int argc, char** argv) {
67 for (int i = 0; i < argc; i++) {
68 if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-help") == 0) {
69 return true;
70 }
71 }
72 return false;
73 }
74
CvdEnvMain(int argc,char ** argv)75 Result<void> CvdEnvMain(int argc, char** argv) {
76 ::android::base::InitLogging(argv, android::base::StderrLogger);
77 if (ContainHelpOption(argc, argv)) {
78 std::cout << kCvdEnvHelpMessage;
79 return {};
80 }
81
82 CF_EXPECT(argc >= 3, " need to specify a receiver and a command");
83 const auto& receiver = argv[1];
84 const auto& cmd = argv[2];
85
86 std::vector<std::string> args;
87 for (int i = 3; i < argc; i++) {
88 // Ignore options, not to be applied when calling grpc_cli.
89 if (!android::base::StartsWith(argv[i], '-')) {
90 args.push_back(argv[i]);
91 }
92 }
93 if (args.size() > 0) {
94 CF_EXPECT(args[0].compare(kServiceControlEnvProxy) != 0,
95 "Prohibited service name");
96 }
97
98 const auto* config = CuttlefishConfig::Get();
99 CF_EXPECT(config != nullptr, "Unable to find the config");
100 const auto& instances = config->Instances();
101 auto receiver_instance = std::find_if(
102 begin(instances), end(instances), [&receiver](const auto& instance) {
103 return receiver == instance.instance_name();
104 });
105
106 CF_EXPECT(receiver_instance != std::end(instances),
107 "there is no instance of which name is "
108 << receiver << ". please check instance name by cvd fleet");
109
110 auto command_output =
111 CF_EXPECT(HandleCmds(receiver_instance->grpc_socket_path(), cmd, args));
112
113 std::cout << command_output;
114
115 return {};
116 }
117
118 } // namespace
119 } // namespace cuttlefish
120
main(int argc,char ** argv)121 int main(int argc, char** argv) {
122 const auto& ret = cuttlefish::CvdEnvMain(argc, argv);
123 CHECK(ret.ok()) << ret.error().FormatForEnv();
124 return 0;
125 }
126