| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This component launches the codelab examples. The example contains directories for each part of |
| // the codelab, and this component accepts a command line argument to choose which part to launch. |
| // |
| // In addition to launching the codelab, this component also launches the fizzbuzz component that |
| // the codelab depends on. |
| |
| #include <fuchsia/examples/inspect/cpp/fidl.h> |
| #include <fuchsia/sys/cpp/fidl.h> |
| #include <lib/sys/cpp/service_directory.h> |
| #include <stdio.h> |
| |
| #include <chrono> |
| #include <iostream> |
| #include <thread> |
| |
| constexpr char fizzbuzz_url[] = |
| "fuchsia-pkg://fuchsia.com/inspect_cpp_codelab#meta/inspect_cpp_codelab_fizzbuzz.cmx"; |
| |
| std::string GetComponentUrl(const std::string& argument) { |
| return "fuchsia-pkg://fuchsia.com/inspect_cpp_codelab#meta/inspect_cpp_codelab_part_" + argument + |
| ".cmx"; |
| } |
| |
| void Usage(char* name) { |
| printf( |
| "Usage: %s <option> <string> [string...]\n option: The server to run. For example \"1\" for " |
| "part_1\n string: Strings provided on the command line to reverse\n", |
| name ? name : ""); |
| exit(1); |
| } |
| |
| int main(int argc, char** argv) { |
| // Parse the input argument to create a component URL. |
| // This component launches the server and connects to it, but first we need to know which part of |
| // the codelab to start. |
| std::string reverser_component_url; |
| if (argc >= 3) { |
| reverser_component_url = GetComponentUrl(argv[1]); |
| } |
| |
| // If no url is specified, print the usage information and exit. |
| if (reverser_component_url == "") { |
| Usage(argc >= 1 ? argv[0] : nullptr); |
| } |
| |
| auto incoming_services = sys::ServiceDirectory::CreateFromNamespace(); |
| |
| fuchsia::sys::EnvironmentSyncPtr env; |
| incoming_services->Connect(env.NewRequest()); |
| |
| fuchsia::sys::EnvironmentSyncPtr child_env; |
| fuchsia::sys::EnvironmentControllerSyncPtr child_env_controller; |
| fuchsia::sys::LauncherSyncPtr launcher; |
| |
| zx::channel fizzbuzz_directory_client, fizzbuzz_directory_server; |
| { |
| fuchsia::io::DirectorySyncPtr req; |
| fizzbuzz_directory_server = req.NewRequest().TakeChannel(); |
| fizzbuzz_directory_client = req.Unbind().TakeChannel(); |
| } |
| |
| // We need to include the FizzBuzz service in the environment we are creating for the codelab. |
| // This code adds additional services to the nested environment so it knows to look for the |
| // service in the out/svc directory of the newly created component. |
| auto env_service_list = std::make_unique<fuchsia::sys::ServiceList>(); |
| env_service_list->names.push_back(fuchsia::examples::inspect::FizzBuzz::Name_); |
| env_service_list->host_directory = std::move(fizzbuzz_directory_client); |
| |
| // Create an environment called "codelab" to contain the new components. |
| if (ZX_OK != env->CreateNestedEnvironment(child_env.NewRequest(), |
| child_env_controller.NewRequest(), "codelab", |
| std::move(env_service_list) /* additional_services */, |
| {.inherit_parent_services = true} /* options */)) { |
| printf("Failed to create nested environment\n"); |
| exit(1); |
| } |
| |
| // Get the launcher needed to create components in the nested environment. |
| if (ZX_OK != child_env->GetLauncher(launcher.NewRequest())) { |
| printf("Failed to get launcher\n"); |
| exit(1); |
| } |
| |
| // Launch the FizzBuzz service component by URL. |
| { |
| fuchsia::sys::LaunchInfo launch_info; |
| launch_info.url = fizzbuzz_url; |
| launch_info.directory_request = std::move(fizzbuzz_directory_server); |
| if (ZX_OK != launcher->CreateComponent(std::move(launch_info), nullptr /* controller */)) { |
| printf("Failed to launch component %s\n", fizzbuzz_url); |
| exit(1); |
| } |
| } |
| |
| // Launch the component by URL. |
| fuchsia::io::DirectorySyncPtr directory_request; |
| { |
| fuchsia::sys::LaunchInfo launch_info; |
| launch_info.url = reverser_component_url; |
| launch_info.directory_request = directory_request.NewRequest().TakeChannel(); |
| if (ZX_OK != launcher->CreateComponent(std::move(launch_info), nullptr /* controller */)) { |
| printf("Failed to launch component %s\n", reverser_component_url.c_str()); |
| exit(1); |
| } |
| } |
| |
| // Create a service directory to connect to services exposed by the created component. |
| sys::ServiceDirectory services(directory_request.Unbind()); |
| |
| // Connect to the reverser service provided by the launched component. |
| fuchsia::examples::inspect::ReverserSyncPtr reverser; |
| services.Connect(reverser.NewRequest()); |
| |
| // [START reverse_loop] |
| // Repeatedly send strings to be reversed to the other component. |
| for (int i = 2; i < argc; i++) { |
| printf("Input: %s\n", argv[i]); |
| |
| std::string output; |
| if (ZX_OK != reverser->Reverse(argv[i], &output)) { |
| printf("Error: Failed to reverse string.\nPerhaps %s was not found?\n", |
| reverser_component_url.c_str()); |
| exit(1); |
| } |
| |
| printf("Output: %s\n", output.c_str()); |
| fflush(stdout); |
| } |
| // [END reverse_loop] |
| |
| printf("Done. Press Ctrl+C to exit\n"); |
| fflush(stdout); |
| while (true) { |
| std::this_thread::sleep_for(std::chrono::seconds(1)); |
| } |
| |
| return 0; |
| } |