[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:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@@ -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 \
 | 
			
		||||
 
 | 
			
		||||
@@ -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
									
								
							
							
						
						
									
										85
									
								
								include/gbinder_bridge.h
									
									
									
									
									
										Normal 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:
 | 
			
		||||
 */
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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
									
								
							
							
						
						
									
										251
									
								
								src/gbinder_bridge.c
									
									
									
									
									
										Normal 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:
 | 
			
		||||
 */
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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(
 | 
			
		||||
 
 | 
			
		||||
@@ -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
									
								
							
							
						
						
									
										268
									
								
								src/gbinder_proxy_object.c
									
									
									
									
									
										Normal 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:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										66
									
								
								src/gbinder_proxy_object.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/gbinder_proxy_object.h
									
									
									
									
									
										Normal 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:
 | 
			
		||||
 */
 | 
			
		||||
@@ -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(
 | 
			
		||||
 
 | 
			
		||||
@@ -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 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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();
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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
									
								
							
							
						
						
									
										140
									
								
								test/binder-bridge/Makefile
									
									
									
									
									
										Normal 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)
 | 
			
		||||
							
								
								
									
										193
									
								
								test/binder-bridge/binder-bridge.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								test/binder-bridge/binder-bridge.c
									
									
									
									
									
										Normal 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:
 | 
			
		||||
 */
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user