[gbinder] Added GBinderBridge object. JB#52557

It acts as a proxy between two binder devices.

This version works for binder transactions which only
pass serialized data back and forth. Passing remote
object references is not yet supported.
This commit is contained in:
Slava Monich
2021-01-26 19:51:45 +02:00
parent 207f9398b4
commit d6dac912dd
25 changed files with 1187 additions and 60 deletions

View File

@@ -75,6 +75,7 @@ LIB = $(LIB_NAME).a
#
SRC = \
gbinder_bridge.c \
gbinder_buffer.c \
gbinder_cleanup.c \
gbinder_client.c \
@@ -88,6 +89,7 @@ SRC = \
gbinder_local_reply.c \
gbinder_local_request.c \
gbinder_log.c \
gbinder_proxy_object.c \
gbinder_reader.c \
gbinder_remote_object.c \
gbinder_remote_reply.c \

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2019 Jolla Ltd.
* Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2021 Jolla Ltd.
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -35,6 +35,7 @@
/* Convenience header to pull in everything at once */
#include "gbinder_bridge.h"
#include "gbinder_buffer.h"
#include "gbinder_client.h"
#include "gbinder_local_object.h"

85
include/gbinder_bridge.h Normal file
View File

@@ -0,0 +1,85 @@
/*
* Copyright (C) 2021 Jolla Ltd.
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GBINDER_BRIDGE_H
#define GBINDER_BRIDGE_H
#include "gbinder_types.h"
/* Since 1.1.4 */
/*
* As of time of this writing, bridging only works for binder transactions
* which only involve passing serialized data back and forth. It doesn't
* work with transactions which pass references to remote objects.
*/
G_BEGIN_DECLS
/*
* A binder bridge object.
*
* For example, bridging "foobar" with interfaces ["example@1.0::IFoo",
* "example@1.0::IBar"] would:
*
* 1. Watch "example@1.0::IFoo/foobar" and "example@1.0::IBar/foobar" on dest
* 2. When those names appears, register objects with the same name on src
* 3. Pass calls coming from src to the dest objects and replies in the
* opposite direction
* 4. When dest objects disappear, remove the corresponding bridging objects
* from src
*
* and so on.
*/
GBinderBridge*
gbinder_bridge_new(
const char* name,
const char* const* ifaces,
GBinderServiceManager* src,
GBinderServiceManager* dest);
void
gbinder_bridge_free(
GBinderBridge* bridge);
G_END_DECLS
#endif /* GBINDER_BRIDGE_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/

View File

@@ -59,6 +59,7 @@ G_BEGIN_DECLS
* 6. Reader parses the data coming with RemoteRequest and RemoteReply
*/
typedef struct gbinder_bridge GBinderBridge;
typedef struct gbinder_buffer GBinderBuffer;
typedef struct gbinder_client GBinderClient;
typedef struct gbinder_ipc GBinderIpc;

View File

@@ -6,7 +6,7 @@ License: BSD
URL: https://github.com/mer-hybris/libgbinder
Source: %{name}-%{version}.tar.bz2
%define libglibutil_version 1.0.35
%define libglibutil_version 1.0.49
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(libglibutil) >= %{libglibutil_version}

251
src/gbinder_bridge.c Normal file
View File

@@ -0,0 +1,251 @@
/*
* Copyright (C) 2021 Jolla Ltd.
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "gbinder_local_request.h"
#include "gbinder_local_reply.h"
#include "gbinder_proxy_object.h"
#include "gbinder_remote_request_p.h"
#include "gbinder_remote_reply.h"
#include "gbinder_remote_object_p.h"
#include "gbinder_servicename.h"
#include "gbinder_servicemanager_p.h"
#include "gbinder_client_p.h"
#include "gbinder_bridge.h"
#include "gbinder_ipc.h"
#include "gbinder_log.h"
#include <gutil_strv.h>
#include <gutil_macros.h>
#include <errno.h>
typedef struct gbinder_bridge_interface {
GBinderBridge* bridge;
char* iface;
char* fqname;
char* name;
gulong dest_watch_id;
gulong dest_death_id;
GBinderRemoteObject* dest_obj;
GBinderServiceName* src_name;
GBinderProxyObject* proxy;
} GBinderBridgeInterface;
struct gbinder_bridge {
GBinderBridgeInterface** ifaces;
GBinderServiceManager* src;
GBinderServiceManager* dest;
};
/*==========================================================================*
* Implementation
*==========================================================================*/
static
void
gbinder_bridge_dest_drop_remote_object(
GBinderBridgeInterface* bi)
{
if (bi->dest_obj) {
GDEBUG("Detached from %s", bi->fqname);
gbinder_remote_object_remove_handler(bi->dest_obj, bi->dest_death_id);
gbinder_remote_object_unref(bi->dest_obj);
bi->dest_death_id = 0;
bi->dest_obj = NULL;
}
}
static
void
gbinder_bridge_interface_deactivate(
GBinderBridgeInterface* bi)
{
gbinder_bridge_dest_drop_remote_object(bi);
if (bi->proxy) {
gbinder_local_object_drop(GBINDER_LOCAL_OBJECT(bi->proxy));
bi->proxy = NULL;
}
if (bi->src_name) {
gbinder_servicename_unref(bi->src_name);
}
}
static
void
gbinder_bridge_interface_free(
GBinderBridgeInterface* bi)
{
GBinderBridge* bridge = bi->bridge;
gbinder_bridge_interface_deactivate(bi);
gbinder_servicemanager_remove_handler(bridge->dest, bi->dest_watch_id);
g_free(bi->iface);
g_free(bi->fqname);
g_free(bi->name);
gutil_slice_free(bi);
}
static
void
gbinder_bridge_dest_death_proc(
GBinderRemoteObject* obj,
void* user_data)
{
GBinderBridgeInterface* bi = user_data;
GDEBUG("%s has died", bi->fqname);
gbinder_bridge_dest_drop_remote_object(bi);
}
static
void
gbinder_bridge_interface_activate(
GBinderBridgeInterface* bi)
{
GBinderBridge* bridge = bi->bridge;
GBinderServiceManager* src = bridge->src;
GBinderServiceManager* dest = bridge->dest;
if (bi->dest_obj && gbinder_remote_object_is_dead(bi->dest_obj)) {
gbinder_bridge_dest_drop_remote_object(bi);
}
if (!bi->dest_obj) {
bi->dest_obj = gbinder_servicemanager_get_service_sync(dest,
bi->fqname, NULL);
if (bi->dest_obj) {
GDEBUG("Attached to %s", bi->fqname);
gbinder_remote_object_ref(bi->dest_obj);
bi->dest_death_id = gbinder_remote_object_add_death_handler
(bi->dest_obj, gbinder_bridge_dest_death_proc, bi);
}
}
if (bi->dest_obj && !bi->proxy) {
bi->proxy = gbinder_proxy_object_new(gbinder_servicemanager_ipc(src),
bi->dest_obj);
}
if (bi->proxy && !bi->src_name) {
bi->src_name = gbinder_servicename_new(src,
GBINDER_LOCAL_OBJECT(bi->proxy), bi->name);
}
}
static
void
gbinder_bridge_dest_registration_proc(
GBinderServiceManager* sm,
const char* name,
void* user_data)
{
GBinderBridgeInterface* bi = user_data;
if (!g_strcmp0(name, bi->fqname)) {
GDEBUG("%s has been registered", bi->fqname);
gbinder_bridge_interface_activate(bi);
}
}
static
GBinderBridgeInterface*
gbinder_bridge_interface_new(
GBinderBridge* self,
const char* name,
const char* iface)
{
GBinderBridgeInterface* bi = g_slice_new0(GBinderBridgeInterface);
bi->bridge = self;
bi->iface = g_strdup(iface);
bi->fqname = g_strconcat(iface, "/", name, NULL);
bi->name = g_strdup(name);
bi->dest_watch_id = gbinder_servicemanager_add_registration_handler
(self->dest, bi->fqname, gbinder_bridge_dest_registration_proc, bi);
/* Try to activate at startup */
gbinder_bridge_interface_activate(bi);
return bi;
}
/*==========================================================================*
* Interface
*==========================================================================*/
GBinderBridge*
gbinder_bridge_new(
const char* name,
const char* const* ifaces,
GBinderServiceManager* src,
GBinderServiceManager* dest)
{
const guint n = gutil_strv_length((const GStrV*)ifaces);
if (G_LIKELY(name) && G_LIKELY(n) && G_LIKELY(src) && G_LIKELY(dest)) {
GBinderBridge* self = g_slice_new0(GBinderBridge);
guint i;
self->src = gbinder_servicemanager_ref(src);
self->dest = gbinder_servicemanager_ref(dest);
self->ifaces = g_new(GBinderBridgeInterface*, n + 1);
for (i = 0; i < n; i++) {
self->ifaces[i] = gbinder_bridge_interface_new(self,
name, ifaces[i]);
}
self->ifaces[i] = NULL;
return self;
}
return NULL;
}
void
gbinder_bridge_free(
GBinderBridge* self)
{
if (G_LIKELY(self)) {
GBinderBridgeInterface** bi = self->ifaces;
while (*bi) {
gbinder_bridge_interface_free(*bi);
bi++;
}
gbinder_servicemanager_unref(self->src);
gbinder_servicemanager_unref(self->dest);
g_free(self->ifaces);
gutil_slice_free(self);
}
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/

View File

@@ -813,6 +813,13 @@ gbinder_driver_io(
return self->io;
}
const GBinderRpcProtocol*
gbinder_driver_protocol(
GBinderDriver* self)
{
return self->protocol;
}
gboolean
gbinder_driver_request_death_notification(
GBinderDriver* self,

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2021 Jolla Ltd.
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -74,6 +74,11 @@ gbinder_driver_io(
GBinderDriver* driver)
GBINDER_INTERNAL;
const GBinderRpcProtocol*
gbinder_driver_protocol(
GBinderDriver* driver)
GBINDER_INTERNAL;
gboolean
gbinder_driver_request_death_notification(
GBinderDriver* driver,
@@ -112,7 +117,7 @@ gbinder_driver_release(
void
gbinder_driver_close_fds(
GBinderDriver* self,
GBinderDriver* driver,
void** objects,
const void* end)
GBINDER_INTERNAL;
@@ -160,7 +165,7 @@ gbinder_driver_ping(
GBinderLocalRequest*
gbinder_driver_local_request_new(
GBinderDriver* self,
GBinderDriver* driver,
const char* iface)
GBINDER_INTERNAL;

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2021 Jolla Ltd.
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -53,6 +53,7 @@ struct gbinder_local_object_priv {
G_DEFINE_TYPE(GBinderLocalObject, gbinder_local_object, G_TYPE_OBJECT)
#define PARENT_CLASS gbinder_local_object_parent_class
#define GBINDER_LOCAL_OBJECT_GET_CLASS(obj) \
G_TYPE_INSTANCE_GET_CLASS((obj), GBINDER_TYPE_LOCAL_OBJECT, \
GBinderLocalObjectClass)
@@ -256,6 +257,18 @@ gbinder_local_object_default_handle_looper_transaction(
return handler(self, req, status);
}
static
void
gbinder_local_object_default_drop(
GBinderLocalObject* self)
{
GBinderLocalObjectPriv* priv = self->priv;
/* Clear the transaction callback */
priv->txproc = NULL;
priv->user_data = NULL;
}
static
void
gbinder_local_object_handle_later(
@@ -336,13 +349,24 @@ gbinder_local_object_new(
GBinderLocalTransactFunc txproc,
void* user_data) /* Since 1.0.30 */
{
if (G_LIKELY(ipc)) {
GBinderLocalObject* self = g_object_new
(GBINDER_TYPE_LOCAL_OBJECT, NULL);
return gbinder_local_object_new_with_type(GBINDER_TYPE_LOCAL_OBJECT,
ipc, ifaces, txproc, user_data);
}
gbinder_local_object_init_base(self, ipc, ifaces, txproc, user_data);
gbinder_ipc_register_local_object(ipc, self);
return self;
GBinderLocalObject*
gbinder_local_object_new_with_type(
GType type,
GBinderIpc* ipc,
const char* const* ifaces,
GBinderLocalTransactFunc txproc,
void* arg)
{
if (G_LIKELY(ipc)) {
GBinderLocalObject* obj = g_object_new(type, NULL);
gbinder_local_object_init_base(obj, ipc, ifaces, txproc, arg);
gbinder_ipc_register_local_object(ipc, obj);
return obj;
}
return NULL;
}
@@ -409,11 +433,7 @@ gbinder_local_object_drop(
GBinderLocalObject* self)
{
if (G_LIKELY(self)) {
GBinderLocalObjectPriv* priv = self->priv;
/* Clear the transaction callback */
priv->txproc = NULL;
priv->user_data = NULL;
GBINDER_LOCAL_OBJECT_GET_CLASS(self)->drop(self);
g_object_unref(GBINDER_LOCAL_OBJECT(self));
}
}
@@ -555,26 +575,26 @@ gbinder_local_object_init(
static
void
gbinder_local_object_dispose(
GObject* local)
GObject* object)
{
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(object);
gbinder_ipc_local_object_disposed(self->ipc, self);
G_OBJECT_CLASS(gbinder_local_object_parent_class)->dispose(local);
G_OBJECT_CLASS(PARENT_CLASS)->dispose(object);
}
static
void
gbinder_local_object_finalize(
GObject* local)
GObject* object)
{
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(local);
GBinderLocalObject* self = GBINDER_LOCAL_OBJECT(object);
GBinderLocalObjectPriv* priv = self->priv;
GASSERT(!self->strong_refs);
gbinder_ipc_unref(self->ipc);
g_strfreev(priv->ifaces);
G_OBJECT_CLASS(gbinder_local_object_parent_class)->finalize(local);
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
}
static
@@ -594,6 +614,7 @@ gbinder_local_object_class_init(
gbinder_local_object_default_handle_looper_transaction;
klass->can_handle_transaction =
gbinder_local_object_default_can_handle_transaction;
klass->drop = gbinder_local_object_default_drop;
gbinder_local_object_signals[SIGNAL_WEAK_REFS_CHANGED] =
g_signal_new(SIGNAL_WEAK_REFS_CHANGED_NAME,

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2021 Jolla Ltd.
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -76,6 +76,7 @@ typedef struct gbinder_local_object_class {
GBinderLocalReply* (*handle_looper_transaction)
(GBinderLocalObject* self, GBinderRemoteRequest* req, guint code,
guint flags, int* status);
void (*drop)(GBinderLocalObject* self);
/* Need to add some placeholders if this class becomes public */
} GBinderLocalObjectClass;
@@ -89,6 +90,15 @@ GType gbinder_local_object_get_type(void) GBINDER_INTERNAL;
#define gbinder_local_object_dev(obj) (gbinder_driver_dev((obj)->ipc->driver))
#define gbinder_local_object_io(obj) (gbinder_driver_io((obj)->ipc->driver))
GBinderLocalObject*
gbinder_local_object_new_with_type(
GType type,
GBinderIpc* ipc,
const char* const* ifaces,
GBinderLocalTransactFunc txproc,
void* user_data)
GBINDER_INTERNAL;
void
gbinder_local_object_init_base(
GBinderLocalObject* self,

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018 Jolla Ltd.
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2021 Jolla Ltd.
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -14,8 +14,8 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -111,11 +111,22 @@ gbinder_local_request_new_from_data(
(gbinder_buffer_io(buffer), NULL);
if (self) {
gbinder_writer_data_set_contents(&self->data, buffer);
gbinder_writer_data_append_contents(&self->data, buffer, 0);
}
return self;
}
void
gbinder_local_request_append_contents(
GBinderLocalRequest* self,
GBinderBuffer* buffer,
gsize offset)
{
if (self) {
gbinder_writer_data_append_contents(&self->data, buffer, offset);
}
}
static
void
gbinder_local_request_free(

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2021 Jolla Ltd.
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -53,6 +53,13 @@ gbinder_local_request_new_from_data(
GBinderBuffer* buffer)
GBINDER_INTERNAL;
void
gbinder_local_request_append_contents(
GBinderLocalRequest* req,
GBinderBuffer* buffer,
gsize offset)
GBINDER_INTERNAL;
#endif /* GBINDER_LOCAL_REQUEST_PRIVATE_H */
/*

268
src/gbinder_proxy_object.c Normal file
View File

@@ -0,0 +1,268 @@
/*
* Copyright (C) 2021 Jolla Ltd.
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include "gbinder_proxy_object.h"
#include "gbinder_local_object_p.h"
#include "gbinder_local_request.h"
#include "gbinder_local_reply.h"
#include "gbinder_remote_object_p.h"
#include "gbinder_remote_request_p.h"
#include "gbinder_remote_reply.h"
#include "gbinder_ipc.h"
#include <gutil_macros.h>
#include <errno.h>
typedef GBinderLocalObjectClass GBinderProxyObjectClass;
typedef struct gbinder_proxy_tx GBinderProxyTx;
struct gbinder_proxy_tx {
GBinderProxyTx* next;
GBinderRemoteRequest* req;
GBinderProxyObject* proxy;
gulong id;
};
struct gbinder_proxy_object_priv {
gboolean dropped;
GBinderProxyTx* tx;
};
GType gbinder_proxy_object_get_type(void) GBINDER_INTERNAL;
G_DEFINE_TYPE(GBinderProxyObject, gbinder_proxy_object, \
GBINDER_TYPE_LOCAL_OBJECT)
#define PARENT_CLASS gbinder_proxy_object_parent_class
/*==========================================================================*
* Implementation
*==========================================================================*/
static
void
gbinder_proxy_tx_dequeue(
GBinderProxyTx* tx)
{
GBinderProxyObject* proxy = tx->proxy;
if (proxy) {
GBinderProxyObjectPriv* priv = proxy->priv;
if (priv->tx) {
if (priv->tx == tx) {
priv->tx = tx->next;
} else {
GBinderProxyTx* prev = priv->tx;
while (prev->next) {
if (prev->next == tx) {
prev->next = tx->next;
break;
}
prev = prev->next;
}
}
}
tx->next = NULL;
tx->proxy = NULL;
g_object_unref(proxy);
}
}
static
void
gbinder_proxy_tx_reply(
GBinderIpc* ipc,
GBinderRemoteReply* reply,
int status,
void* user_data)
{
GBinderProxyTx* tx = user_data;
GBinderLocalReply* fwd = gbinder_remote_reply_copy_to_local(reply);
tx->id = 0;
gbinder_proxy_tx_dequeue(tx);
gbinder_remote_request_complete(tx->req, fwd, status);
gbinder_local_reply_unref(fwd);
}
static
void
gbinder_proxy_tx_destroy(
gpointer user_data)
{
GBinderProxyTx* tx = user_data;
gbinder_proxy_tx_dequeue(tx);
gbinder_remote_request_unref(tx->req);
gutil_slice_free(tx);
}
static
GBinderLocalReply*
gbinder_proxy_object_handle_transaction(
GBinderLocalObject* object,
GBinderRemoteRequest* req,
guint code,
guint flags,
int* status)
{
GBinderProxyObject* self = GBINDER_PROXY_OBJECT(object);
GBinderProxyObjectPriv* priv = self->priv;
GBinderRemoteObject* remote = self->remote;
if (!priv->dropped && !gbinder_remote_object_is_dead(remote)) {
GBinderIpc* remote_ipc = remote->ipc;
GBinderDriver* remote_driver = remote_ipc->driver;
GBinderLocalRequest* fwd =
gbinder_remote_request_translate_to_local(req, remote_driver);
GBinderProxyTx* tx = g_slice_new0(GBinderProxyTx);
g_object_ref(tx->proxy = self);
tx->req = gbinder_remote_request_ref(req);
tx->next = priv->tx;
priv->tx = tx;
/* Mark the incoming request as pending */
gbinder_remote_request_block(req);
/* Forward the transaction */
tx->id = gbinder_ipc_transact(remote_ipc, remote->handle, code, flags,
fwd , gbinder_proxy_tx_reply, gbinder_proxy_tx_destroy, tx);
gbinder_local_request_unref(fwd);
*status = GBINDER_STATUS_OK;
} else {
*status = (-EBADMSG);
}
return NULL;
}
static
GBINDER_LOCAL_TRANSACTION_SUPPORT
gbinder_proxy_object_can_handle_transaction(
GBinderLocalObject* self,
const char* iface,
guint code)
{
/* Process all transactions on the main thread */
return GBINDER_LOCAL_TRANSACTION_SUPPORTED;
}
static
void
gbinder_proxy_object_drop(
GBinderLocalObject* object)
{
GBinderProxyObject* self = GBINDER_PROXY_OBJECT(object);
GBinderProxyObjectPriv* priv = self->priv;
priv->dropped = TRUE;
GBINDER_LOCAL_OBJECT_CLASS(PARENT_CLASS)->drop(object);
}
/*==========================================================================*
* Interface
*==========================================================================*/
GBinderProxyObject*
gbinder_proxy_object_new(
GBinderIpc* src,
GBinderRemoteObject* remote)
{
if (G_LIKELY(remote)) {
/*
* We don't need to specify the interface list because all
* transactions (including HIDL_GET_DESCRIPTOR_TRANSACTION
* and HIDL_DESCRIPTOR_CHAIN_TRANSACTION) are getting forwared
* to the remote object.
*/
GBinderLocalObject* object = gbinder_local_object_new_with_type
(GBINDER_TYPE_PROXY_OBJECT, src, NULL, NULL, NULL);
if (object) {
GBinderProxyObject* self = GBINDER_PROXY_OBJECT(object);
self->remote = gbinder_remote_object_ref(remote);
return self;
}
}
return NULL;
}
/*==========================================================================*
* Internals
*==========================================================================*/
static
void
gbinder_proxy_object_finalize(
GObject* object)
{
GBinderProxyObject* self = GBINDER_PROXY_OBJECT(object);
gbinder_remote_object_unref(self->remote);
G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
}
static
void
gbinder_proxy_object_init(
GBinderProxyObject* self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, GBINDER_TYPE_PROXY_OBJECT,
GBinderProxyObjectPriv);
}
static
void
gbinder_proxy_object_class_init(
GBinderProxyObjectClass* klass)
{
GObjectClass* object_class = G_OBJECT_CLASS(klass);
g_type_class_add_private(klass, sizeof(GBinderProxyObjectPriv));
object_class->finalize = gbinder_proxy_object_finalize;
klass->can_handle_transaction = gbinder_proxy_object_can_handle_transaction;
klass->handle_transaction = gbinder_proxy_object_handle_transaction;
klass->drop = gbinder_proxy_object_drop;
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2021 Jolla Ltd.
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GBINDER_PROXY_OBJECT_H
#define GBINDER_PROXY_OBJECT_H
#include "gbinder_local_object_p.h"
typedef struct gbinder_proxy_object_priv GBinderProxyObjectPriv;
struct gbinder_proxy_object {
GBinderLocalObject parent;
GBinderProxyObjectPriv* priv;
GBinderRemoteObject* remote;
};
GType gbinder_proxy_object_get_type(void) GBINDER_INTERNAL;
#define GBINDER_TYPE_PROXY_OBJECT gbinder_proxy_object_get_type()
#define GBINDER_PROXY_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
GBINDER_TYPE_PROXY_OBJECT, GBinderProxyObject))
/* Registers with src and forwards all transactions to the remote */
GBinderProxyObject*
gbinder_proxy_object_new(
GBinderIpc* src,
GBinderRemoteObject* remote)
GBINDER_INTERNAL;
#endif /* GBINDER_PROXY_OBJECT_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018 Jolla Ltd.
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2021 Jolla Ltd.
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -14,8 +14,8 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -36,6 +36,7 @@
#include "gbinder_local_request_p.h"
#include "gbinder_object_registry.h"
#include "gbinder_buffer_p.h"
#include "gbinder_driver.h"
#include "gbinder_log.h"
#include <gutil_macros.h>
@@ -90,6 +91,32 @@ gbinder_remote_request_copy_to_local(
return NULL;
}
GBinderLocalRequest*
gbinder_remote_request_translate_to_local(
GBinderRemoteRequest* req,
GBinderDriver* driver)
{
GBinderRemoteRequestPriv* self = gbinder_remote_request_cast(req);
if (G_LIKELY(self)) {
GBinderReaderData* data = &self->data;
if (!driver || (gbinder_driver_protocol(driver) == self->protocol)) {
/* The same protocol, the same format of RPC header */
return gbinder_local_request_new_from_data(data->buffer);
} else {
/* Need to translate to another format */
GBinderLocalRequest* local = gbinder_driver_local_request_new
(driver, self->iface);
gbinder_local_request_append_contents(local, data->buffer,
self->header_size);
return local;
}
}
return NULL;
}
static
void
gbinder_remote_request_free(

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2021 Jolla Ltd.
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -56,6 +56,12 @@ gbinder_remote_request_set_data(
GBinderBuffer* buffer)
GBINDER_INTERNAL;
GBinderLocalRequest*
gbinder_remote_request_translate_to_local(
GBinderRemoteRequest* req,
GBinderDriver* driver)
GBINDER_INTERNAL;
#endif /* GBINDER_REMOTE_REQUEST_PRIVATE_H */
/*

View File

@@ -88,6 +88,8 @@ GType gbinder_servicemanager_get_type(void) GBINDER_INTERNAL;
G_TYPE_CHECK_CLASS_CAST((klass), GBINDER_TYPE_SERVICEMANAGER, \
GBinderServiceManagerClass)
#define gbinder_servicemanager_ipc(sm) gbinder_client_ipc(sm->client)
GBinderServiceManager*
gbinder_servicemanager_new_with_type(
GType type,

View File

@@ -42,6 +42,7 @@ typedef struct gbinder_handler GBinderHandler;
typedef struct gbinder_io GBinderIo;
typedef struct gbinder_object_registry GBinderObjectRegistry;
typedef struct gbinder_output_data GBinderOutputData;
typedef struct gbinder_proxy_object GBinderProxyObject;
typedef struct gbinder_rpc_protocol GBinderRpcProtocol;
typedef struct gbinder_servicepoll GBinderServicePoll;
typedef struct gbinder_ipc_looper_tx GBinderIpcLooperTx;

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2021 Jolla Ltd.
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -68,25 +68,35 @@ gbinder_writer_data_set_contents(
GBinderWriterData* data,
GBinderBuffer* buffer)
{
gsize bufsize;
const guint8* bufdata = gbinder_buffer_data(buffer, &bufsize);
const GBinderIo* io = gbinder_buffer_io(buffer);
GBinderBufferContents* contents = gbinder_buffer_contents(buffer);
GASSERT(data->io == io);
g_byte_array_set_size(data->bytes, 0);
gutil_int_array_set_count(data->offsets, 0);
data->buffers_size = 0;
gbinder_cleanup_reset(data->cleanup);
gbinder_writer_data_append_contents(data, buffer, 0);
}
void
gbinder_writer_data_append_contents(
GBinderWriterData* data,
GBinderBuffer* buffer,
gsize off)
{
GBinderBufferContents* contents = gbinder_buffer_contents(buffer);
g_byte_array_append(data->bytes, bufdata, bufsize);
if (contents) {
gsize bufsize;
const guint8* bufdata = gbinder_buffer_data(buffer, &bufsize);
void** objects = gbinder_buffer_objects(buffer);
if (off < bufsize) {
g_byte_array_append(data->bytes, bufdata + off, bufsize - off);
}
data->cleanup = gbinder_cleanup_add(data->cleanup,
gbinder_writer_data_buffer_cleanup,
gbinder_buffer_contents_ref(contents));
if (objects && *objects) {
const GBinderIo* io = gbinder_buffer_io(buffer);
if (!data->offsets) {
data->offsets = gutil_int_array_new();
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2021 Jolla Ltd.
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -57,6 +57,13 @@ gbinder_writer_data_set_contents(
GBinderBuffer* buffer)
GBINDER_INTERNAL;
void
gbinder_writer_data_append_contents(
GBinderWriterData* data,
GBinderBuffer* buffer,
gsize data_offset)
GBINDER_INTERNAL;
void
gbinder_writer_data_append_bool(
GBinderWriterData* data,

View File

@@ -2,6 +2,7 @@
all:
%:
@$(MAKE) -C binder-bridge $*
@$(MAKE) -C binder-client $*
@$(MAKE) -C binder-dump $*
@$(MAKE) -C binder-list $*

140
test/binder-bridge/Makefile Normal file
View File

@@ -0,0 +1,140 @@
# -*- Mode: makefile-gmake -*-
.PHONY: all debug release clean cleaner
.PHONY: libgbinder-release libgbinder-debug
#
# Required packages
#
PKGS = glib-2.0 gio-2.0 gio-unix-2.0 libglibutil
#
# Default target
#
all: debug release
#
# Executable
#
EXE = binder-bridge
#
# Sources
#
SRC = $(EXE).c
#
# Directories
#
SRC_DIR = .
BUILD_DIR = build
LIB_DIR = ../..
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
#
# Tools and flags
#
CC ?= $(CROSS_COMPILE)gcc
LD = $(CC)
WARNINGS = -Wall
INCLUDES = -I$(LIB_DIR)/include
BASE_FLAGS = -fPIC
CFLAGS = $(BASE_FLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \
$(shell pkg-config --cflags $(PKGS))
LDFLAGS = $(BASE_FLAGS) $(shell pkg-config --libs $(PKGS))
QUIET_MAKE = make --no-print-directory
DEBUG_FLAGS = -g
RELEASE_FLAGS =
ifndef KEEP_SYMBOLS
KEEP_SYMBOLS = 0
endif
ifneq ($(KEEP_SYMBOLS),0)
RELEASE_FLAGS += -g
SUBMAKE_OPTS += KEEP_SYMBOLS=1
endif
DEBUG_LDFLAGS = $(LDFLAGS) $(DEBUG_FLAGS)
RELEASE_LDFLAGS = $(LDFLAGS) $(RELEASE_FLAGS)
DEBUG_CFLAGS = $(CFLAGS) $(DEBUG_FLAGS) -DDEBUG
RELEASE_CFLAGS = $(CFLAGS) $(RELEASE_FLAGS) -O2
#
# Files
#
DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
DEBUG_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_so)
RELEASE_SO_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_so)
DEBUG_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_link)
RELEASE_LINK_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_link)
DEBUG_SO = $(LIB_DIR)/$(DEBUG_SO_FILE)
RELEASE_SO = $(LIB_DIR)/$(RELEASE_SO_FILE)
#
# Dependencies
#
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(DEPS)),)
-include $(DEPS)
endif
endif
$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
#
# Rules
#
DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE)
RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE)
debug: libgbinder-debug $(DEBUG_EXE)
release: libgbinder-release $(RELEASE_EXE)
clean:
rm -f *~
rm -fr $(BUILD_DIR)
cleaner: clean
@make -C $(LIB_DIR) clean
$(DEBUG_BUILD_DIR):
mkdir -p $@
$(RELEASE_BUILD_DIR):
mkdir -p $@
$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
$(DEBUG_EXE): $(DEBUG_SO) $(DEBUG_BUILD_DIR) $(DEBUG_OBJS)
$(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) $< -o $@
$(RELEASE_EXE): $(RELEASE_SO) $(RELEASE_BUILD_DIR) $(RELEASE_OBJS)
$(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) $< -o $@
ifeq ($(KEEP_SYMBOLS),0)
strip $@
endif
libgbinder-debug:
@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(DEBUG_SO_FILE) $(DEBUG_LINK_FILE)
libgbinder-release:
@make $(SUBMAKE_OPTS) -C $(LIB_DIR) $(RELEASE_SO_FILE) $(RELEASE_LINK_FILE)

View File

@@ -0,0 +1,193 @@
/*
* Copyright (C) 2021 Jolla Ltd.
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <gbinder.h>
#include <gutil_log.h>
#include <glib-unix.h>
#define RET_OK (0)
#define RET_NODEV (1)
#define RET_INVARG (2)
typedef struct app_options {
const char* src;
const char* dest;
const char* name;
const char** ifaces;
} AppOptions;
static
gboolean
app_signal(
gpointer loop)
{
GINFO("Caught signal, shutting down...");
g_main_loop_quit(loop);
return G_SOURCE_CONTINUE;
}
static
int
app_run(
const AppOptions* opt)
{
int ret = RET_NODEV;
GBinderServiceManager* src = gbinder_servicemanager_new(opt->src);
if (src) {
GBinderServiceManager* dest = gbinder_servicemanager_new(opt->dest);
if (dest) {
GMainLoop* loop = g_main_loop_new(NULL, TRUE);
guint sigtrm = g_unix_signal_add(SIGTERM, app_signal, loop);
guint sigint = g_unix_signal_add(SIGINT, app_signal, loop);
GBinderBridge* bridge = gbinder_bridge_new
(opt->name, opt->ifaces, src, dest);
g_main_loop_run(loop);
if (sigtrm) g_source_remove(sigtrm);
if (sigint) g_source_remove(sigint);
g_main_loop_unref(loop);
gbinder_bridge_free(bridge);
gbinder_servicemanager_unref(dest);
ret = RET_OK;
} else {
GERR("No servicemanager at %s", opt->dest);
}
gbinder_servicemanager_unref(src);
} else {
GERR("No servicemanager at %s", opt->src);
}
return ret;
}
static
gboolean
app_log_verbose(
const gchar* name,
const gchar* value,
gpointer data,
GError** error)
{
gutil_log_default.level = GLOG_LEVEL_VERBOSE;
return TRUE;
}
static
gboolean
app_log_quiet(
const gchar* name,
const gchar* value,
gpointer data,
GError** error)
{
gutil_log_default.level = GLOG_LEVEL_NONE;
return TRUE;
}
static
gboolean
app_init(
AppOptions* opt,
int argc,
char* argv[])
{
gboolean ok = FALSE;
GOptionEntry entries[] = {
{ "verbose", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
app_log_verbose, "Enable verbose output", NULL },
{ "quiet", 'q', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
app_log_quiet, "Be quiet", NULL },
{ NULL }
};
GError* error = NULL;
GOptionContext* options = g_option_context_new("SRC DST NAME IFACES...");
gutil_log_timestamp = FALSE;
gutil_log_default.level = GLOG_LEVEL_DEFAULT;
g_option_context_add_main_entries(options, entries, NULL);
g_option_context_set_summary(options,
"Forwards calls from device SRC to device DST.");
if (g_option_context_parse(options, &argc, &argv, &error)) {
if (argc >= 5) {
int i;
const int first_iface = 4;
opt->src = argv[1];
opt->dest = argv[2];
opt->name = argv[3];
opt->ifaces = g_new(const char*, argc - first_iface + 1);
for (i = first_iface; i < argc; i++) {
opt->ifaces[i - first_iface] = argv[i];
}
opt->ifaces[i - first_iface] = NULL;
ok = TRUE;
} else {
char* help = g_option_context_get_help(options, TRUE, NULL);
fprintf(stderr, "%s", help);
g_free(help);
}
} else {
GERR("%s", error->message);
g_error_free(error);
}
g_option_context_free(options);
return ok;
}
int main(int argc, char* argv[])
{
AppOptions opt;
int ret = RET_INVARG;
memset(&opt, 0, sizeof(opt));
if (app_init(&opt, argc, argv)) {
ret = app_run(&opt);
}
g_free(opt.ifaces);
return ret;
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2019 Jolla Ltd.
* Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2021 Jolla Ltd.
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -14,8 +14,8 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -36,6 +36,7 @@
#include "gbinder_handler.h"
#include "gbinder_local_request_p.h"
#include "gbinder_output_data.h"
#include "gbinder_rpc_protocol.h"
#include <poll.h>
@@ -60,6 +61,9 @@ test_basic(
driver = gbinder_driver_new(dev, NULL);
g_assert(driver);
g_assert(!g_strcmp0(dev, gbinder_driver_dev(driver)));
g_assert(gbinder_driver_protocol(driver));
g_assert(gbinder_driver_protocol(driver) ==
gbinder_rpc_protocol_for_device(dev));
g_assert(gbinder_driver_ref(driver) == driver);
gbinder_driver_unref(driver);
gbinder_driver_free_buffer(driver, NULL);

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018 Jolla Ltd.
* Copyright (C) 2018 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2018-2021 Jolla Ltd.
* Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
@@ -14,8 +14,8 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -87,6 +87,7 @@ test_null(
g_assert(!gbinder_remote_request_read_string8(NULL));
g_assert(!gbinder_remote_request_read_string16(NULL));
g_assert(!gbinder_remote_request_read_object(NULL));
g_assert(!gbinder_remote_request_translate_to_local(NULL, NULL));
}
/*==========================================================================*