aboutsummaryrefslogtreecommitdiffstats
path: root/src/main-grpc.cc
diff options
context:
space:
mode:
authorScott Murray <scott.murray@konsulko.com>2022-09-10 12:15:20 -0400
committerScott Murray <scott.murray@konsulko.com>2022-09-21 14:33:32 +0000
commit992f87151ff189dc061624f010eddee2036fd33f (patch)
tree1372b14798ee21610f66b2466061f564ef631a17 /src/main-grpc.cc
parent920f7d6d92ffca4998f6215f4d20ab17693b59db (diff)
Add gRPC API implementationneedlefish
Changes: - Rename the existing daemon to applaunchd-dbus, and add a new version that exposes a gRPC based implementation of the API based on the protobuf definition added in a top-level protos directory. Having both the D-Bus and gRPC APIs exposed by a single daemon was posing difficulties around startup dependencies stemming from D-Bus activation of the daemon. Since the end goal is dropping the D-Bus API entirely, it is easier to just add a second daemon for gRPC that will eventually be the only one present. - To facilitate building the two implementations, a significant amount of code refactoring has been done to move things from the D-Bus API implementing app_launcher.[ch] to systemd_manager.[ch] so the code can be reused. - All use of the systemd D-Bus library except for the path encoding helper function has been replaced with GDBus. The systemd interface wrapper code was generated with gdbus-codegen from XML files captured via introspection on a running system. The motivation for this change was to avoid multithreading issues with sd_bus exposed when calling into it from the gRPC threads. - The copyright headers in the source files have been tweaked to remove the Apache license boilerplate in favour of a SPDX license tag. Notes: - The gRPC API differs slightly from the D-Bus one in that it has a single status streaming RPC method as opposed to the separate signals for application started or terminated that the D-Bus API has. - The gRPC API is currently unauthenticated, the aim is to circle back and implement authentication once a consensus can be reached on what mechanism should be used (fixed JWT configuration, OAuth, etc.). Bug-AGL: SPEC-4559 Signed-off-by: Scott Murray <scott.murray@konsulko.com> Change-Id: I828f38a58b60e9959162b98054982124d4fa4380 (cherry picked from commit c52afaf8b5c96136fe20e5d5a1332121d3b09ee9)
Diffstat (limited to 'src/main-grpc.cc')
-rw-r--r--src/main-grpc.cc85
1 files changed, 85 insertions, 0 deletions
diff --git a/src/main-grpc.cc b/src/main-grpc.cc
new file mode 100644
index 0000000..d94e4aa
--- /dev/null
+++ b/src/main-grpc.cc
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: Apache-2.0
+/*
+ * Copyright (C) 2022 Konsulko Group
+ */
+
+#include <thread>
+#include <chrono>
+#include <glib.h>
+#include <glib-unix.h>
+
+#include "systemd_manager.h"
+#include "AppLauncherImpl.h"
+
+GMainLoop *main_loop = NULL;
+
+AppLauncherImpl *g_service = NULL;
+
+static gboolean quit_cb(gpointer user_data)
+{
+ g_info("Quitting...");
+
+ if (main_loop)
+ g_idle_add(G_SOURCE_FUNC(g_main_loop_quit), main_loop);
+ else
+ exit(0);
+
+ return G_SOURCE_REMOVE;
+}
+
+void RunGrpcServer(std::shared_ptr<Server> &server)
+{
+ // Start server and wait for shutdown
+ server->Wait();
+}
+
+int main(int argc, char *argv[])
+{
+ main_loop = g_main_loop_new(NULL, FALSE);
+
+ SystemdManager *manager = systemd_manager_get_default();
+
+ grpc::EnableDefaultHealthCheckService(true);
+ grpc::reflection::InitProtoReflectionServerBuilderPlugin();
+ ServerBuilder builder;
+
+ // Listen on the given address without any authentication mechanism (for now)
+ std::string server_address("localhost:50052");
+ builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
+
+ // Register "service" as the instance through which we'll communicate with
+ // clients. In this case it corresponds to a *synchronous* service.
+ AppLauncherImpl *service = new AppLauncherImpl(manager);
+ builder.RegisterService(service);
+
+ // Finally assemble the server.
+ std::shared_ptr<Server> server(builder.BuildAndStart());
+ if (!server) {
+ exit(1);
+ }
+ std::cout << "Server listening on " << server_address << std::endl;
+
+ g_unix_signal_add(SIGTERM, quit_cb, (gpointer) &server);
+ g_unix_signal_add(SIGINT, quit_cb, (gpointer) &server);
+
+ // Start gRPC API server on its own thread
+ std::thread grpc_thread(RunGrpcServer, std::ref(server));
+
+ g_main_loop_run(main_loop);
+
+ // Service implementation may have threads blocked from client streaming
+ // RPCs, make sure those exit.
+ service->Shutdown();
+
+ // Need to set a deadline to avoid blocking on clients doing streaming
+ // RPC reads
+ server->Shutdown(std::chrono::system_clock::now() + std::chrono::milliseconds(500));
+
+ grpc_thread.join();
+
+ g_object_unref(manager);
+
+ g_main_loop_unref(main_loop);
+
+ return 0;
+}