Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 346212d1 authored by David Brazdil's avatar David Brazdil Committed by Automerger Merge Worker
Browse files

Merge "rpc_binder: Refactor C/Rust bindings to control server lifetime" am: 81a86779

parents fca46f62 81a86779
Loading
Loading
Loading
Loading
+28 −16
Original line number Diff line number Diff line
@@ -17,20 +17,41 @@
#pragma once

#include <sys/socket.h>
#include <stdint.h>

extern "C" {

struct AIBinder;
struct ARpcServer;

// Starts an RPC server on a given port and a given root IBinder object.
// This function sets up the server and joins before returning.
bool RunVsockRpcServer(AIBinder* service, unsigned int port);
// Returns an opaque handle to the running server instance, or null if the server
// could not be started.
[[nodiscard]] ARpcServer* ARpcServer_newVsock(AIBinder* service, unsigned int port);

// Starts an RPC server on a given port and a given root IBinder object.
// This function sets up the server, calls readyCallback with a given param, and
// then joins before returning.
bool RunVsockRpcServerCallback(AIBinder* service, unsigned int port,
                               void (*readyCallback)(void* param), void* param);
// Starts a Unix domain RPC server with a given init-managed Unix domain `name`
// and a given root IBinder object.
// The socket should be created in init.rc with the same `name`.
// Returns an opaque handle to the running server instance, or null if the server
// could not be started.
[[nodiscard]] ARpcServer* ARpcServer_newInitUnixDomain(AIBinder* service, const char* name);

// Runs ARpcServer_join() in a background thread. Immediately returns.
void ARpcServer_start(ARpcServer* server);

// Joins the thread of a running RpcServer instance. At any given point, there
// can only be one thread calling ARpcServer_join().
// If a client needs to actively terminate join, call ARpcServer_shutdown() in
// a separate thread.
void ARpcServer_join(ARpcServer* server);

// Shuts down any running ARpcServer_join().
void ARpcServer_shutdown(ARpcServer* server);

// Frees the ARpcServer handle and drops the reference count on the underlying
// RpcServer instance. The handle must not be reused afterwards.
// This automatically calls ARpcServer_shutdown().
void ARpcServer_free(ARpcServer* server);

// Starts an RPC server on a given port and a given root IBinder factory.
// RunVsockRpcServerWithFactory acts like RunVsockRpcServerCallback, but instead of
@@ -42,15 +63,6 @@ bool RunVsockRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* c

AIBinder* VsockRpcClient(unsigned int cid, unsigned int port);

// Starts a Unix domain RPC server with a given init-managed Unix domain `name` and
// a given root IBinder object.
// The socket should be created in init.rc with the same `name`.
//
// This function sets up the server, calls readyCallback with a given param, and
// then joins before returning.
bool RunInitUnixDomainRpcServer(AIBinder* service, const char* name,
                                void (*readyCallback)(void* param), void* param);

// Gets the service via the RPC binder with Unix domain socket with the given
// Unix socket `name`.
// The final Unix domain socket path name is /dev/socket/`name`.
+53 −32
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@
 * limitations under the License.
 */

#include <binder_rpc_unstable.hpp>

#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <android/binder_libbinder.h>
@@ -25,23 +27,32 @@
using android::OK;
using android::RpcServer;
using android::RpcSession;
using android::sp;
using android::status_t;
using android::statusToString;
using android::base::unique_fd;

extern "C" {
// Opaque handle for RpcServer.
struct ARpcServer {};

void RunRpcServer(android::sp<RpcServer>& server, AIBinder* service,
                  void (*readyCallback)(void* param), void* param) {
    server->setRootObject(AIBinder_toPlatformBinder(service));
static sp<RpcServer> toRpcServer(ARpcServer* handle) {
    auto ref = reinterpret_cast<RpcServer*>(handle);
    return sp<RpcServer>::fromExisting(ref);
}

    if (readyCallback) readyCallback(param);
    server->join();
static ARpcServer* createRpcServerHandle(sp<RpcServer>& server) {
    auto ref = server.get();
    ref->incStrong(ref);
    return reinterpret_cast<ARpcServer*>(ref);
}

    // Shutdown any open sessions since server failed.
    (void)server->shutdown();
static void freeRpcServerHandle(ARpcServer* handle) {
    auto ref = reinterpret_cast<RpcServer*>(handle);
    ref->decStrong(ref);
}

extern "C" {

bool RunVsockRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* context),
                                  void* factoryContext, unsigned int port) {
    auto server = RpcServer::make();
@@ -64,47 +75,57 @@ bool RunVsockRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* c
    return true;
}

bool RunVsockRpcServerCallback(AIBinder* service, unsigned int port,
                               void (*readyCallback)(void* param), void* param) {
ARpcServer* ARpcServer_newVsock(AIBinder* service, unsigned int port) {
    auto server = RpcServer::make();
    if (status_t status = server->setupVsockServer(port); status != OK) {
        LOG(ERROR) << "Failed to set up vsock server with port " << port
                   << " error: " << statusToString(status).c_str();
        return false;
    }
    RunRpcServer(server, service, readyCallback, param);
    return true;
}

bool RunVsockRpcServer(AIBinder* service, unsigned int port) {
    return RunVsockRpcServerCallback(service, port, nullptr, nullptr);
}

AIBinder* VsockRpcClient(unsigned int cid, unsigned int port) {
    auto session = RpcSession::make();
    if (status_t status = session->setupVsockClient(cid, port); status != OK) {
        LOG(ERROR) << "Failed to set up vsock client with CID " << cid << " and port " << port
                   << " error: " << statusToString(status).c_str();
        return nullptr;
    }
    return AIBinder_fromPlatformBinder(session->getRootObject());
    server->setRootObject(AIBinder_toPlatformBinder(service));
    return createRpcServerHandle(server);
}

bool RunInitUnixDomainRpcServer(AIBinder* service, const char* name,
                                void (*readyCallback)(void* param), void* param) {
ARpcServer* ARpcServer_newInitUnixDomain(AIBinder* service, const char* name) {
    auto server = RpcServer::make();
    auto fd = unique_fd(android_get_control_socket(name));
    if (!fd.ok()) {
        LOG(ERROR) << "Failed to get fd for the socket:" << name;
        return false;
        return nullptr;
    }
    if (status_t status = server->setupRawSocketServer(std::move(fd)); status != OK) {
        LOG(ERROR) << "Failed to set up Unix Domain RPC server with name " << name
                   << " error: " << statusToString(status).c_str();
        return false;
        return nullptr;
    }
    RunRpcServer(server, service, readyCallback, param);
    return true;
    server->setRootObject(AIBinder_toPlatformBinder(service));
    return createRpcServerHandle(server);
}

void ARpcServer_start(ARpcServer* handle) {
    toRpcServer(handle)->start();
}

void ARpcServer_join(ARpcServer* handle) {
    toRpcServer(handle)->join();
}

void ARpcServer_shutdown(ARpcServer* handle) {
    toRpcServer(handle)->shutdown();
}

void ARpcServer_free(ARpcServer* handle) {
    freeRpcServerHandle(handle);
}

AIBinder* VsockRpcClient(unsigned int cid, unsigned int port) {
    auto session = RpcSession::make();
    if (status_t status = session->setupVsockClient(cid, port); status != OK) {
        LOG(ERROR) << "Failed to set up vsock client with CID " << cid << " and port " << port
                   << " error: " << statusToString(status).c_str();
        return nullptr;
    }
    return AIBinder_fromPlatformBinder(session->getRootObject());
}

AIBinder* UnixDomainRpcClient(const char* name) {
+6 −3
Original line number Diff line number Diff line
LIBBINDER_RPC_UNSTABLE_SHIM { # platform-only
  global:
    RunVsockRpcServer;
    RunVsockRpcServerCallback;
    ARpcServer_free;
    ARpcServer_join;
    ARpcServer_newInitUnixDomain;
    ARpcServer_newVsock;
    ARpcServer_shutdown;
    ARpcServer_start;
    VsockRpcClient;
    RunInitUnixDomainRpcServer;
    UnixDomainRpcClient;
    RpcPreconnectedClient;
  local:
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ rust_library {
        "libbinder_rpc_unstable_bindgen_sys",
        "libbinder_rs",
        "libdowncast_rs",
        "libforeign_types",
        "liblibc",
        "liblog_rust",
    ],
+1 −3
Original line number Diff line number Diff line
@@ -23,6 +23,4 @@ pub use client::{
    get_preconnected_rpc_interface, get_preconnected_rpc_service, get_unix_domain_rpc_interface,
    get_unix_domain_rpc_service, get_vsock_rpc_interface, get_vsock_rpc_service,
};
pub use server::{
    run_init_unix_domain_rpc_server, run_vsock_rpc_server, run_vsock_rpc_server_with_factory,
};
pub use server::{run_vsock_rpc_server_with_factory, RpcServer, RpcServerRef};
Loading