From b29ea9115ea3277354b7ccbe442026279220f4ac Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Mon, 11 Aug 2003 02:11:58 +0000 Subject: 2003-08-10 Havoc Pennington * tools/dbus-send.c (main): add --type argument, for now supporting only method_call and signal types. * tools/dbus-print-message.c: print message type * dbus/dbus-connection.c (_dbus_connection_new_for_transport): init connection->objects * doc/dbus-specification.sgml: fix sgml * bus/*.c: port over to object-instance API changes * test/test-service.c: ditto * dbus/dbus-message.c (dbus_message_create_header): allow #NULL name, we will have to fix up the rest of the code to also handle this (dbus_message_new): generic message-creation call (set_string_field): allow appending name field --- glib/test-dbus-glib.c | 4 ++-- glib/test-profile.c | 2 +- glib/test-thread-client.c | 2 +- glib/test-thread-server.c | 27 ++++++++++++++------------- 4 files changed, 18 insertions(+), 17 deletions(-) (limited to 'glib') diff --git a/glib/test-dbus-glib.c b/glib/test-dbus-glib.c index d963ee3d..d4b5f9b2 100644 --- a/glib/test-dbus-glib.c +++ b/glib/test-dbus-glib.c @@ -30,8 +30,8 @@ main (int argc, char **argv) dbus_connection_setup_with_g_main (connection, NULL); - message = dbus_message_new (DBUS_MESSAGE_HELLO, - DBUS_SERVICE_DBUS); + message = dbus_message_new_method_call (DBUS_MESSAGE_HELLO, + DBUS_SERVICE_DBUS); dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error); diff --git a/glib/test-profile.c b/glib/test-profile.c index f213c676..6d13e32f 100644 --- a/glib/test-profile.c +++ b/glib/test-profile.c @@ -38,7 +38,7 @@ send_echo_message (DBusConnection *connection) { DBusMessage *message; - message = dbus_message_new (ECHO_MESSAGE, NULL); + message = dbus_message_new_method_call (ECHO_MESSAGE, NULL); dbus_message_append_args (message, DBUS_TYPE_STRING, "Hello World!", DBUS_TYPE_INT32, 123456, diff --git a/glib/test-thread-client.c b/glib/test-thread-client.c index 02ebdf67..a3290b27 100644 --- a/glib/test-thread-client.c +++ b/glib/test-thread-client.c @@ -19,7 +19,7 @@ thread_func (gpointer data) while (1) { - message = dbus_message_new ("org.freedesktop.ThreadTest", NULL); + message = dbus_message_new_method_call ("org.freedesktop.ThreadTest", NULL); dbus_message_append_iter_init (message, &iter); diff --git a/glib/test-thread-server.c b/glib/test-thread-server.c index 00044a79..4cc886fd 100644 --- a/glib/test-thread-server.c +++ b/glib/test-thread-server.c @@ -42,6 +42,9 @@ handle_test_message (DBusMessageHandler *handler, char *str, *expected_str; GString *counter_str; int i; + + if (!dbus_message_has_name (message, "org.freedesktop.ThreadTest")) + return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; dbus_message_iter_init (message, &iter); @@ -124,7 +127,7 @@ handle_test_message (DBusMessageHandler *handler, g_string_free (counter_str, TRUE); out: - return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + return DBUS_HANDLER_RESULT_REMOVE_MESSAGE; } static DBusHandlerResult @@ -132,7 +135,7 @@ handle_filter (DBusMessageHandler *handler, DBusConnection *connection, DBusMessage *message, void *user_data) -{ +{ return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; } @@ -142,20 +145,20 @@ handle_disconnect (DBusMessageHandler *handler, DBusMessage *message, void *user_data) { + if (!dbus_message_has_name (message, DBUS_MESSAGE_LOCAL_DISCONNECT)) + return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + g_print ("connection disconnected\n"); dbus_connection_unref (connection); - - return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + + return DBUS_HANDLER_RESULT_REMOVE_MESSAGE; } - static void new_connection_callback (DBusServer *server, DBusConnection *new_connection, void *user_data) { - const char *test_messages[] = { "org.freedesktop.ThreadTest" }; - const char *disconnect_messages[] = { "org.freedesktop.Local.Disconnect" }; DBusMessageHandler *test_message_handler; ThreadTestData * data; @@ -170,9 +173,8 @@ new_connection_callback (DBusServer *server, dbus_message_handler_new (handle_test_message, data, (DBusFreeFunction)thread_test_data_free); - if (!dbus_connection_register_handler (new_connection, - test_message_handler, - test_messages, 1)) + if (!dbus_connection_add_filter (new_connection, + test_message_handler)) goto nomem; if (!dbus_connection_set_data (new_connection, @@ -181,9 +183,8 @@ new_connection_callback (DBusServer *server, (DBusFreeFunction)dbus_message_handler_unref)) goto nomem; - if (!dbus_connection_register_handler (new_connection, - disconnect_handler, - disconnect_messages, 1)) + if (!dbus_connection_add_filter (new_connection, + disconnect_handler)) goto nomem; if (!dbus_connection_add_filter (new_connection, -- cgit From 5c1a8e44903bd1dedc8cbefad78b0c8b61daada5 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Tue, 12 Aug 2003 02:43:50 +0000 Subject: 2003-08-11 Havoc Pennington * bus/test.c (client_disconnect_handler): change to return HANDLED (would have been REMOVE_MESSAGE) * dbus/dbus-object.h (enum DBusHandlerResult): rename to HANDLED/NOT_YET_HANDLED instead of REMOVE_MESSAGE/ALLOW_MORE_HANDLERS to make it clearer how it should be used. --- glib/test-profile.c | 6 ++++-- glib/test-thread-server.c | 10 +++++----- 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'glib') diff --git a/glib/test-profile.c b/glib/test-profile.c index 6d13e32f..852bd091 100644 --- a/glib/test-profile.c +++ b/glib/test-profile.c @@ -76,9 +76,10 @@ client_filter (DBusMessageHandler *handler, exit (0); } send_echo_message (connection); + return DBUS_HANDLER_RESULT_HANDLED; } - return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } static void* @@ -147,9 +148,10 @@ server_filter (DBusMessageHandler *handler, ECHO_MESSAGE)) { send_echo_message (connection); + return DBUS_HANDLER_RESULT_HANDLED; } - return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } static void diff --git a/glib/test-thread-server.c b/glib/test-thread-server.c index 4cc886fd..3ad1f907 100644 --- a/glib/test-thread-server.c +++ b/glib/test-thread-server.c @@ -44,7 +44,7 @@ handle_test_message (DBusMessageHandler *handler, int i; if (!dbus_message_has_name (message, "org.freedesktop.ThreadTest")) - return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; dbus_message_iter_init (message, &iter); @@ -127,7 +127,7 @@ handle_test_message (DBusMessageHandler *handler, g_string_free (counter_str, TRUE); out: - return DBUS_HANDLER_RESULT_REMOVE_MESSAGE; + return DBUS_HANDLER_RESULT_HANDLED; } static DBusHandlerResult @@ -136,7 +136,7 @@ handle_filter (DBusMessageHandler *handler, DBusMessage *message, void *user_data) { - return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } static DBusHandlerResult @@ -146,12 +146,12 @@ handle_disconnect (DBusMessageHandler *handler, void *user_data) { if (!dbus_message_has_name (message, DBUS_MESSAGE_LOCAL_DISCONNECT)) - return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; g_print ("connection disconnected\n"); dbus_connection_unref (connection); - return DBUS_HANDLER_RESULT_REMOVE_MESSAGE; + return DBUS_HANDLER_RESULT_HANDLED; } static void -- cgit From 9d1c3a0f8428f4b052899ab12c706961efb003d4 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 13 Aug 2003 22:14:47 +0000 Subject: new file, just fooling around --- glib/dbus-gidl.h | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 glib/dbus-gidl.h (limited to 'glib') diff --git a/glib/dbus-gidl.h b/glib/dbus-gidl.h new file mode 100644 index 00000000..a5dc6cb0 --- /dev/null +++ b/glib/dbus-gidl.h @@ -0,0 +1,80 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-gidl.h data structure describing an interface, to be generated from IDL + * or something + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef DBUS_GLIB_IDL_H +#define DBUS_GLIB_IDL_H + +#include +#include + +G_BEGIN_DECLS + +typedef struct InterfaceInfo InterfaceInfo; +typedef struct MethodInfo MethodInfo; +typedef struct SignalInfo SignalInfo; +typedef struct ArgInfo ArgInfo; + +typedef enum +{ + ARG_IN, + ARG_OUT +} ArgDirection; + +typedef enum +{ + METHOD_SYNC, + METHOD_ASYNC, + METHOD_CANCELLABLE +} MethodStyle; + +InterfaceInfo* interface_info_new (void); +void interface_info_ref (InterfaceInfo *info); +void interface_info_unref (InterfaceInfo *info); +GSList* interface_info_get_methods (InterfaceInfo *info); +GSList* interface_info_get_signals (InterfaceInfo *info); + +MethodInfo* method_info_new (void); +void method_info_ref (MethodInfo *info); +void method_info_unref (MethodInfo *info); + +const char* method_info_get_name (MethodInfo *info); +GSList* method_info_get_args (MethodInfo *info); +MethodStyle method_info_get_style (MethodInfo *info); + +SignalInfo* signal_info_new (void); +void signal_info_ref (SignalInfo *info); +void signal_info_unref (SignalInfo *info); + +const char* signal_info_get_name (SignalInfo *info); +GSList* signal_info_get_args (SignalInfo *info); + +ArgInfo* arg_info_new (void); +void arg_info_ref (ArgInfo *info); +void arg_info_unref (ArgInfo *info); +const char* arg_info_get_name (ArgInfo *info); +int arg_info_get_type (ArgInfo *info); +ArgDirection arg_info_get_direction (ArgInfo *info); + +G_END_DECLS + +#endif /* DBUS_GLIB_IDL_H */ -- cgit From a6c8a71b1bcba04b63812a61f668e87af0922e5e Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Thu, 14 Aug 2003 22:49:13 +0000 Subject: 2003-08-14 Havoc Pennington * dbus/dbus-pending-call.c: start on new object that will replace DBusMessageHandler and ReplyHandlerData for tracking outstanding replies * dbus/dbus-gproxy.c: start on proxy object used to communicate with remote interfaces * dbus/dbus-gidl.c: do the boring boilerplate in here --- glib/Makefile.am | 15 ++- glib/dbus-compiler-main.c | 48 +++++++ glib/dbus-gidl.c | 331 ++++++++++++++++++++++++++++++++++++++++++++++ glib/dbus-gidl.h | 19 ++- glib/dbus-glib.h | 4 + glib/dbus-gproxy.c | 170 ++++++++++++++++++++++++ glib/dbus-gproxy.h | 79 +++++++++++ 7 files changed, 660 insertions(+), 6 deletions(-) create mode 100644 glib/dbus-compiler-main.c create mode 100644 glib/dbus-gidl.c create mode 100644 glib/dbus-gproxy.c create mode 100644 glib/dbus-gproxy.h (limited to 'glib') diff --git a/glib/Makefile.am b/glib/Makefile.am index ebdb932f..8cc09eb7 100644 --- a/glib/Makefile.am +++ b/glib/Makefile.am @@ -1,18 +1,29 @@ -INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_GLIB_CFLAGS) +INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_GLIB_CFLAGS) -DDBUS_COMPILATION=1 dbusincludedir=$(includedir)/dbus-1.0/dbus lib_LTLIBRARIES=libdbus-glib-1.la dbusinclude_HEADERS= \ - dbus-glib.h + dbus-glib.h \ + dbus-gproxy.h libdbus_glib_1_la_SOURCES = \ dbus-gmain.c \ + dbus-gproxy.c \ dbus-gthread.c libdbus_glib_1_la_LIBADD= $(DBUS_GLIB_LIBS) $(top_builddir)/dbus/libdbus-1.la +bin_PROGRAMS=dbus-glib-compiler + +dbus_glib_compiler_SOURCES = \ + dbus-gidl.c \ + dbus-gidl.h \ + dbus-compiler-main.c + +dbus_glib_compiler_LDADD= libdbus-glib-1.la $(DBUS_GLIB_LIBS) $(top_builddir)/dbus/libdbus-1.la + if DBUS_BUILD_TESTS if HAVE_GLIB_THREADS diff --git a/glib/dbus-compiler-main.c b/glib/dbus-compiler-main.c new file mode 100644 index 00000000..d8bf7bde --- /dev/null +++ b/glib/dbus-compiler-main.c @@ -0,0 +1,48 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-compiler-main.c main() for GLib stubs/skels generator + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "dbus-gidl.h" + +int +main (int argc, char **argv) +{ + + + return 0; +} + +#ifdef DBUS_BUILD_TESTS + +/** + * @ingroup DBusGCompiler + * Unit test for GLib stubs/skels compiler + * @returns #TRUE on success. + */ +dbus_bool_t +_dbus_gcompiler_test (void) +{ + + return TRUE; +} + +#endif /* DBUS_BUILD_TESTS */ diff --git a/glib/dbus-gidl.c b/glib/dbus-gidl.c new file mode 100644 index 00000000..b6e0fb8c --- /dev/null +++ b/glib/dbus-gidl.c @@ -0,0 +1,331 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-gidl.c data structure describing an interface, to be generated from IDL + * or something + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "dbus-gidl.h" + +struct InterfaceInfo +{ + int refcount; + char *name; + GSList *methods; + GSList *signals; +}; + +struct MethodInfo +{ + int refcount; + GSList *args; + char *name; + MethodStyle style; +}; + +struct SignalInfo +{ + int refcount; + GSList *args; + char *name; +}; + +struct ArgInfo +{ + int refcount; + char *name; + int type; + ArgDirection direction; +}; + +static void +free_method_list (GSList **methods_p) +{ + GSList *tmp; + tmp = *methods_p; + while (tmp != NULL) + { + method_info_unref (tmp->data); + tmp = tmp->next; + } + g_slist_free (*methods_p); + *methods_p = NULL; +} + +static void +free_signal_list (GSList **signals_p) +{ + GSList *tmp; + tmp = *signals_p; + while (tmp != NULL) + { + signal_info_unref (tmp->data); + tmp = tmp->next; + } + g_slist_free (*signals_p); + *signals_p = NULL; +} + +InterfaceInfo* +interface_info_new (const char *name) +{ + InterfaceInfo *info; + + info = g_new0 (InterfaceInfo, 1); + info->refcount = 1; + info->name = g_strdup (name); + + return info; +} + +void +interface_info_ref (InterfaceInfo *info) +{ + info->refcount += 1; +} + +void +interface_info_unref (InterfaceInfo *info) +{ + info->refcount -= 1; + if (info->refcount == 0) + { + free_method_list (&info->methods); + free_signal_list (&info->signals); + g_free (info->name); + g_free (info); + } +} + +GSList* +interface_info_get_methods (InterfaceInfo *info) +{ + return info->methods; +} + +GSList* +interface_info_get_signals (InterfaceInfo *info) +{ + return info->signals; +} + +void +interface_info_add_method (InterfaceInfo *info, + MethodInfo *method) +{ + method_info_ref (method); + info->methods = g_slist_append (info->methods, method); +} + +void +interface_info_add_signal (InterfaceInfo *info, + SignalInfo *signal) +{ + signal_info_ref (signal); + info->signals = g_slist_append (info->signals, signal); +} + +static void +free_arg_list (GSList **args_p) +{ + GSList *tmp; + tmp = *args_p; + while (tmp != NULL) + { + arg_info_unref (tmp->data); + tmp = tmp->next; + } + g_slist_free (*args_p); + *args_p = NULL; +} + +MethodInfo* +method_info_new (const char *name, + MethodStyle style) +{ + MethodInfo *info; + + info = g_new0 (MethodInfo, 1); + info->refcount = 1; + info->name = g_strdup (name); + info->style = style; + + return info; +} + +void +method_info_ref (MethodInfo *info) +{ + info->refcount += 1; +} + +void +method_info_unref (MethodInfo *info) +{ + info->refcount -= 1; + if (info->refcount == 0) + { + free_arg_list (&info->args); + g_free (info->name); + g_free (info); + } +} + +const char* +method_info_get_name (MethodInfo *info) +{ + return info->name; +} + +GSList* +method_info_get_args (MethodInfo *info) +{ + return info->args; +} + +MethodStyle +method_info_get_style (MethodInfo *info) +{ + return info->style; +} + +void +method_info_add_arg (MethodInfo *info, + ArgInfo *arg) +{ + arg_info_ref (arg); + info->args = g_slist_append (info->args, arg); +} + +SignalInfo* +signal_info_new (const char *name) +{ + SignalInfo *info; + + info = g_new0 (SignalInfo, 1); + info->refcount = 1; + info->name = g_strdup (name); + + return info; +} + +void +signal_info_ref (SignalInfo *info) +{ + info->refcount += 1; +} + +void +signal_info_unref (SignalInfo *info) +{ + info->refcount -= 1; + if (info->refcount == 0) + { + free_arg_list (&info->args); + g_free (info->name); + g_free (info); + } +} + +const char* +signal_info_get_name (SignalInfo *info) +{ + return info->name; +} + +GSList* +signal_info_get_args (SignalInfo *info) +{ + return info->args; +} + +void +signal_info_add_arg (SignalInfo *info, + ArgInfo *arg) +{ + arg_info_ref (arg); + info->args = g_slist_append (info->args, arg); +} + +ArgInfo* +arg_info_new (const char *name, + ArgDirection direction, + int type) +{ + ArgInfo *info; + + info = g_new0 (ArgInfo, 1); + info->refcount = 1; + info->name = g_strdup (name); + info->direction = direction; + info->type = type; + + return info; +} + +void +arg_info_ref (ArgInfo *info) +{ + info->refcount += 1; +} + +void +arg_info_unref (ArgInfo *info) +{ + info->refcount -= 1; + if (info->refcount == 0) + { + g_free (info->name); + g_free (info); + } +} +const char* +arg_info_get_name (ArgInfo *info) +{ + return info->name; +} + +int +arg_info_get_type (ArgInfo *info) +{ + return info->type; +} + +ArgDirection +arg_info_get_direction (ArgInfo *info) +{ + return info->direction; +} + +#ifdef DBUS_BUILD_TESTS + +/** + * @ingroup DBusGIDL + * Unit test for GLib IDL internals + * @returns #TRUE on success. + */ +dbus_bool_t +_dbus_gidl_test (void) +{ + + return TRUE; +} + +#endif /* DBUS_BUILD_TESTS */ diff --git a/glib/dbus-gidl.h b/glib/dbus-gidl.h index a5dc6cb0..c3c72d61 100644 --- a/glib/dbus-gidl.h +++ b/glib/dbus-gidl.h @@ -47,28 +47,39 @@ typedef enum METHOD_CANCELLABLE } MethodStyle; -InterfaceInfo* interface_info_new (void); +InterfaceInfo* interface_info_new (const char *name); void interface_info_ref (InterfaceInfo *info); void interface_info_unref (InterfaceInfo *info); GSList* interface_info_get_methods (InterfaceInfo *info); GSList* interface_info_get_signals (InterfaceInfo *info); +void interface_info_add_method (InterfaceInfo *info, + MethodInfo *method); +void interface_info_add_signal (InterfaceInfo *info, + SignalInfo *signal); -MethodInfo* method_info_new (void); +MethodInfo* method_info_new (const char *name, + MethodStyle style); void method_info_ref (MethodInfo *info); void method_info_unref (MethodInfo *info); const char* method_info_get_name (MethodInfo *info); GSList* method_info_get_args (MethodInfo *info); MethodStyle method_info_get_style (MethodInfo *info); +void method_info_add_arg (MethodInfo *info, + ArgInfo *arg); -SignalInfo* signal_info_new (void); +SignalInfo* signal_info_new (const char *name); void signal_info_ref (SignalInfo *info); void signal_info_unref (SignalInfo *info); const char* signal_info_get_name (SignalInfo *info); GSList* signal_info_get_args (SignalInfo *info); +void signal_info_add_arg (SignalInfo *info, + ArgInfo *arg); -ArgInfo* arg_info_new (void); +ArgInfo* arg_info_new (const char *name, + ArgDirection direction, + int type); void arg_info_ref (ArgInfo *info); void arg_info_unref (ArgInfo *info); const char* arg_info_get_name (ArgInfo *info); diff --git a/glib/dbus-glib.h b/glib/dbus-glib.h index c6116c52..7ca22417 100644 --- a/glib/dbus-glib.h +++ b/glib/dbus-glib.h @@ -28,12 +28,16 @@ G_BEGIN_DECLS +#define DBUS_INSIDE_DBUS_GLIB_H 1 + void dbus_gthread_init (void); void dbus_connection_setup_with_g_main (DBusConnection *connection, GMainContext *context); void dbus_server_setup_with_g_main (DBusServer *server, GMainContext *context); +#undef DBUS_INSIDE_DBUS_GLIB_H + G_END_DECLS #endif /* DBUS_GLIB_H */ diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c new file mode 100644 index 00000000..4326057a --- /dev/null +++ b/glib/dbus-gproxy.c @@ -0,0 +1,170 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-gcall.c convenience routines for calling methods, etc. + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include "dbus-gproxy.h" + +/** + * @addtogroup DBusGLibInternals + * + * @{ + */ + +struct DBusGProxy +{ + int refcount; + DBusConnection *connection; + char *service; + char *interface; + DBusObjectID object_id; +}; + +static DBusGProxy* +_dbus_gproxy_new (DBusConnection *connection) +{ + DBusGProxy *proxy; + + proxy = g_new0 (DBusGProxy, 1); + + proxy->refcount = 1; + proxy->connection = connection; + dbus_connection_ref (connection); + + return proxy; +} + +/** @} End of DBusGLibInternals */ + +/** @addtogroup DBusGLib + * @{ + */ + +/** + * Creates a new proxy for a remote interface. Method calls and signal + * connections over this proxy will go to the service owner; the + * service owner is expected to support the given interface name. THE + * SERVICE OWNER MAY CHANGE OVER TIME, for example between two + * different method calls. If you need a fixed owner, you need to + * request the current owner and bind a proxy to that rather than to + * the generic service name; see dbus_gproxy_new_for_service_owner(). + * + * A service-associated proxy only makes sense with a message bus, + * not for app-to-app direct dbus connections. + * + * @param connection the connection to the remote bus or app + * @param service_name name of the service on the message bus + * @param interface_name name of the interface to call methods on + * @returns new proxy object + */ +DBusGProxy* +dbus_gproxy_new_for_service (DBusConnection *connection, + const char *service_name, + const char *interface_name) +{ + DBusGProxy *proxy; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (service_name != NULL, NULL); + g_return_val_if_fail (interface_name != NULL, NULL); + + proxy = _dbus_gproxy_new (connection); + + proxy->service = g_strdup (service_name); + proxy->interface = g_strdup (interface_name); + + return proxy; +} + +/** + * Increment reference count on proxy object. + * + * @param proxy the proxy + */ +void +dbus_gproxy_ref (DBusGProxy *proxy) +{ + g_return_if_fail (proxy != NULL); + + proxy->refcount += 1; +} + +/** + * Decrement reference count on proxy object. + * + * @param proxy the proxy + */ +void +dbus_gproxy_unref (DBusGProxy *proxy) +{ + g_return_if_fail (proxy != NULL); + + proxy->refcount -= 1; + if (proxy->refcount == 0) + { + dbus_connection_unref (proxy->connection); + g_free (proxy->interface); + g_free (proxy->service); + g_free (proxy); + } +} + +/** + * Invokes a method on a remote interface. This function does not + * block; instead it returns an opaque #DBusGPendingCall object that + * tracks the pending call. The method call will not be sent over the + * wire until the application returns to the main loop, or blocks in + * dbus_connection_flush() to write out pending data. The call will + * be completed after a timeout, or when a reply is received. + * + * @param proxy a proxy for a remote interface + * @param method the name of the method to invoke + * @param first_arg_type type of the first argument + * + * @returns opaque pending call object + * + */ +DBusGPendingCall* +dbus_gproxy_begin_call (DBusGProxy *proxy, + const char *method, + int first_arg_type, + ...) +{ + + +} + +/** @} End of DBusGLib public */ + +#ifdef DBUS_BUILD_TESTS + +/** + * @ingroup DBusGLibInternals + * Unit test for GLib proxy functions + * @returns #TRUE on success. + */ +dbus_bool_t +_dbus_gproxy_test (void) +{ + + return TRUE; +} + +#endif /* DBUS_BUILD_TESTS */ diff --git a/glib/dbus-gproxy.h b/glib/dbus-gproxy.h new file mode 100644 index 00000000..bebcd1ce --- /dev/null +++ b/glib/dbus-gproxy.h @@ -0,0 +1,79 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-gproxy.h convenience routines for calling methods, etc. + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef DBUS_GPROXY_H +#define DBUS_GPROXY_H + +#if !defined (DBUS_INSIDE_DBUS_GLIB_H) && !defined (DBUS_COMPILATION) +#error "Only can be included directly, this file may disappear or change contents." +#endif + +#include +#include +#include /* for GCallback at the moment, we don't link to it */ + +G_BEGIN_DECLS + +typedef struct DBusGProxy DBusGProxy; +typedef struct DBusGPendingCall DBusGPendingCall; + +DBusGProxy* dbus_gproxy_new_for_service (DBusConnection *connection, + const char *service_name, + const char *interface_name); +DBusGProxy* dbus_gproxy_new_for_service_owner (DBusConnection *connection, + const char *service_name, + const char *interface_name, + GError **error); +DBusGProxy* dbus_gproxy_new_for_object_id (DBusConnection *connection, + const DBusObjectID *object_id, + const char *interface_name); +DBusGProxy* dbus_gproxy_new_for_interface (DBusConnection *connection, + const char *interface_name); +void dbus_gproxy_ref (DBusGProxy *proxy); +void dbus_gproxy_unref (DBusGProxy *proxy); +gboolean dbus_gproxy_connect_signal (DBusGProxy *proxy, + const char *signal_name, + GCallback callback, + void *data, + GFreeFunc free_data_func, + GError **error); +DBusGPendingCall* dbus_gproxy_begin_call (DBusGProxy *proxy, + const char *method, + int first_arg_type, + ...); +void dbus_gproxy_oneway_call (DBusGProxy *proxy, + const char *method, + int first_arg_type, + ...); + +gboolean dbus_gpending_call_is_complete (DBusGPendingCall *call); +void dbus_gpending_call_cancel_and_free (DBusGPendingCall *call); +gboolean dbus_gpending_call_block_and_free (DBusGPendingCall *call, + GError **error, + int first_arg_type, + ...); + + + +G_END_DECLS + +#endif /* DBUS_GPROXY_H */ -- cgit From a1b0bd33408f03894987ac32b4e6b46c6a15a594 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Fri, 15 Aug 2003 23:10:12 +0000 Subject: 2003-08-15 Havoc Pennington * dbus/dbus-pending-call.c (dbus_pending_call_block): implement * dbus/dbus-connection.c (dbus_connection_send_with_reply_and_block): factor out internals; change to convert any error replies to DBusError instead of returning them as a message --- glib/dbus-gproxy.h | 70 +++++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) (limited to 'glib') diff --git a/glib/dbus-gproxy.h b/glib/dbus-gproxy.h index bebcd1ce..47b70f36 100644 --- a/glib/dbus-gproxy.h +++ b/glib/dbus-gproxy.h @@ -34,43 +34,43 @@ G_BEGIN_DECLS typedef struct DBusGProxy DBusGProxy; -typedef struct DBusGPendingCall DBusGPendingCall; +typedef struct DBusPendingCall DBusPendingCall; -DBusGProxy* dbus_gproxy_new_for_service (DBusConnection *connection, - const char *service_name, - const char *interface_name); -DBusGProxy* dbus_gproxy_new_for_service_owner (DBusConnection *connection, - const char *service_name, - const char *interface_name, - GError **error); -DBusGProxy* dbus_gproxy_new_for_object_id (DBusConnection *connection, - const DBusObjectID *object_id, - const char *interface_name); -DBusGProxy* dbus_gproxy_new_for_interface (DBusConnection *connection, - const char *interface_name); -void dbus_gproxy_ref (DBusGProxy *proxy); -void dbus_gproxy_unref (DBusGProxy *proxy); -gboolean dbus_gproxy_connect_signal (DBusGProxy *proxy, - const char *signal_name, - GCallback callback, - void *data, - GFreeFunc free_data_func, - GError **error); -DBusGPendingCall* dbus_gproxy_begin_call (DBusGProxy *proxy, - const char *method, - int first_arg_type, - ...); -void dbus_gproxy_oneway_call (DBusGProxy *proxy, - const char *method, - int first_arg_type, - ...); +DBusGProxy* dbus_gproxy_new_for_service (DBusConnection *connection, + const char *service_name, + const char *interface_name); +DBusGProxy* dbus_gproxy_new_for_service_owner (DBusConnection *connection, + const char *service_name, + const char *interface_name, + GError **error); +DBusGProxy* dbus_gproxy_new_for_object_id (DBusConnection *connection, + const DBusObjectID *object_id, + const char *interface_name); +DBusGProxy* dbus_gproxy_new_for_interface (DBusConnection *connection, + const char *interface_name); +void dbus_gproxy_ref (DBusGProxy *proxy); +void dbus_gproxy_unref (DBusGProxy *proxy); +gboolean dbus_gproxy_connect_signal (DBusGProxy *proxy, + const char *signal_name, + GCallback callback, + void *data, + GFreeFunc free_data_func, + GError **error); +DBusPendingCall* dbus_gproxy_begin_call (DBusGProxy *proxy, + const char *method, + int first_arg_type, + ...); +void dbus_gproxy_oneway_call (DBusGProxy *proxy, + const char *method, + int first_arg_type, + ...); +gboolean dbus_pending_call_is_complete (DBusPendingCall *call); +void dbus_pending_call_cancel_and_free (DBusPendingCall *call); +gboolean dbus_pending_call_block_and_free (DBusPendingCall *call, + GError **error, + int first_arg_type, + ...); -gboolean dbus_gpending_call_is_complete (DBusGPendingCall *call); -void dbus_gpending_call_cancel_and_free (DBusGPendingCall *call); -gboolean dbus_gpending_call_block_and_free (DBusGPendingCall *call, - GError **error, - int first_arg_type, - ...); -- cgit From 7c3693a53b4eba0db1aebe1edab5ded21eb7757f Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sat, 16 Aug 2003 21:28:47 +0000 Subject: 2003-08-16 Havoc Pennington * dbus/dbus-object-registry.c (add_and_remove_objects): remove broken assertion * glib/dbus-gproxy.c: some hacking --- glib/dbus-gproxy.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++--- glib/dbus-gproxy.h | 17 ++++---- 2 files changed, 121 insertions(+), 14 deletions(-) (limited to 'glib') diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c index 4326057a..36f9724c 100644 --- a/glib/dbus-gproxy.c +++ b/glib/dbus-gproxy.c @@ -30,6 +30,7 @@ struct DBusGProxy { + GStaticMutex lock; int refcount; DBusConnection *connection; char *service; @@ -37,17 +38,22 @@ struct DBusGProxy DBusObjectID object_id; }; +#define LOCK_PROXY(proxy) (g_static_mutex_lock (&(proxy)->lock)) +#define UNLOCK_PROXY(proxy) (g_static_mutex_unlock (&(proxy)->lock)) + static DBusGProxy* _dbus_gproxy_new (DBusConnection *connection) { DBusGProxy *proxy; proxy = g_new0 (DBusGProxy, 1); - + proxy->refcount = 1; proxy->connection = connection; dbus_connection_ref (connection); + g_static_mutex_init (&proxy->lock); + return proxy; } @@ -96,6 +102,8 @@ dbus_gproxy_new_for_service (DBusConnection *connection, /** * Increment reference count on proxy object. * + * @todo use GAtomic to avoid locking + * * @param proxy the proxy */ void @@ -103,11 +111,17 @@ dbus_gproxy_ref (DBusGProxy *proxy) { g_return_if_fail (proxy != NULL); + LOCK_PROXY (proxy); + proxy->refcount += 1; + + UNLOCK_PROXY (proxy); } /** * Decrement reference count on proxy object. + * + * @todo use GAtomic to avoid locking * * @param proxy the proxy */ @@ -116,23 +130,35 @@ dbus_gproxy_unref (DBusGProxy *proxy) { g_return_if_fail (proxy != NULL); - proxy->refcount -= 1; + LOCK_PROXY (proxy); + + proxy->refcount -= 1; + if (proxy->refcount == 0) { + UNLOCK_PROXY (proxy); + dbus_connection_unref (proxy->connection); g_free (proxy->interface); g_free (proxy->service); + g_static_mutex_free (&proxy->lock); g_free (proxy); } + else + { + UNLOCK_PROXY (proxy); + } } /** * Invokes a method on a remote interface. This function does not - * block; instead it returns an opaque #DBusGPendingCall object that + * block; instead it returns an opaque #DBusPendingCall object that * tracks the pending call. The method call will not be sent over the * wire until the application returns to the main loop, or blocks in * dbus_connection_flush() to write out pending data. The call will * be completed after a timeout, or when a reply is received. + * To collect the results of the call (which may be an error, + * or a reply), use dbus_gproxy_end_call(). * * @param proxy a proxy for a remote interface * @param method the name of the method to invoke @@ -141,14 +167,96 @@ dbus_gproxy_unref (DBusGProxy *proxy) * @returns opaque pending call object * */ -DBusGPendingCall* +DBusPendingCall* dbus_gproxy_begin_call (DBusGProxy *proxy, const char *method, int first_arg_type, ...) { + g_return_val_if_fail (proxy != NULL, NULL); + LOCK_PROXY (proxy); + + UNLOCK_PROXY (proxy); +} + +/** + * Collects the results of a method call. The method call was normally + * initiated with dbus_gproxy_end_call(). This function will block if + * the results haven't yet been received; use + * dbus_pending_call_set_notify() to be notified asynchronously that a + * pending call has been completed. + * + * If the call results in an error, the error is set as normal for + * GError and the function returns #FALSE. + * + * Otherwise, the "out" parameters and return value of the + * method are stored in the provided varargs list. + * The list should be terminated with DBUS_TYPE_INVALID. + * + * @param proxy a proxy for a remote interface + * @param pending the pending call from dbus_gproxy_begin_call() + * @param error return location for an error + * @param first_arg_type type of first "out" argument + * @returns #FALSE if an error is set + */ +gboolean +dbus_gproxy_end_call (DBusGProxy *proxy, + DBusPendingCall *pending, + GError **error, + int first_arg_type, + ...) +{ + g_return_val_if_fail (proxy != NULL, FALSE); + LOCK_PROXY (proxy); + + UNLOCK_PROXY (proxy); +} + +/** + * Sends a message to the interface we're proxying for. Does not + * block or wait for a reply. The message is only actually written out + * when you return to the main loop or block in + * dbus_connection_flush(). + * + * The message is modified to be addressed to the target interface. + * That is, a destination service field or whatever is needed + * will be added to the message. + * + * This function adds a reference to the message, so the caller + * still owns its original reference. + * + * @todo fix for sending to interfaces and object IDs + * + * @param proxy a proxy for a remote interface + * @param message the message to address and send + * @param client_serial return location for message's serial, or #NULL + */ +void +dbus_gproxy_send (DBusGProxy *proxy, + DBusMessage *message, + dbus_uint32_t *client_serial) +{ + g_return_if_fail (proxy != NULL); + LOCK_PROXY (proxy); - + if (proxy->service) + { + if (!dbus_message_set_destination (message, proxy->service)) + g_error ("Out of memory\n"); + } + if (proxy->interface) + { + /* FIXME */ + } + if (!dbus_object_id_is_null (&proxy->object_id)) + { + /* FIXME */ + } + + if (!dbus_connection_send (proxy->connection, message, client_serial)) + g_error ("Out of memory\n"); + + UNLOCK_PROXY (proxy); } /** @} End of DBusGLib public */ diff --git a/glib/dbus-gproxy.h b/glib/dbus-gproxy.h index 47b70f36..f40ce8a0 100644 --- a/glib/dbus-gproxy.h +++ b/glib/dbus-gproxy.h @@ -34,7 +34,6 @@ G_BEGIN_DECLS typedef struct DBusGProxy DBusGProxy; -typedef struct DBusPendingCall DBusPendingCall; DBusGProxy* dbus_gproxy_new_for_service (DBusConnection *connection, const char *service_name, @@ -60,18 +59,18 @@ DBusPendingCall* dbus_gproxy_begin_call (DBusGProxy *proxy, const char *method, int first_arg_type, ...); -void dbus_gproxy_oneway_call (DBusGProxy *proxy, - const char *method, +gboolean dbus_gproxy_end_call (DBusGProxy *proxy, + DBusPendingCall *pending, + GError **error, int first_arg_type, ...); -gboolean dbus_pending_call_is_complete (DBusPendingCall *call); -void dbus_pending_call_cancel_and_free (DBusPendingCall *call); -gboolean dbus_pending_call_block_and_free (DBusPendingCall *call, - GError **error, +void dbus_gproxy_oneway_call (DBusGProxy *proxy, + const char *method, int first_arg_type, ...); - - +void dbus_gproxy_send (DBusGProxy *proxy, + DBusMessage *message, + dbus_uint32_t *client_serial); G_END_DECLS -- cgit From 68a3c593b9e77b33614726363c7b6fd85d113021 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Mon, 18 Aug 2003 22:43:30 +0000 Subject: 2003-08-18 Havoc Pennington * dbus/dbus-hash.c (_dbus_hash_table_insert_two_strings): fix * dbus/dbus-message.c (_dbus_message_loader_queue_messages): fix dumb bug created earlier (wrong order of args to decode_header_data()) * tools/dbus-send.c: port * tools/dbus-print-message.c (print_message): port * test/data/*messages: port all messages over * dbus/dbus-message-builder.c: support including message type * bus/driver.c: port over * bus/dispatch.c: port over to new stuff * dbus/dbus-connection.c (_dbus_connection_new_for_transport): rename disconnect signal to "Disconnected" --- glib/test-dbus-glib.c | 7 ++++--- glib/test-profile.c | 28 ++++++++++++++++++++-------- glib/test-thread-client.c | 3 ++- glib/test-thread-server.c | 6 ++++-- 4 files changed, 30 insertions(+), 14 deletions(-) (limited to 'glib') diff --git a/glib/test-dbus-glib.c b/glib/test-dbus-glib.c index d4b5f9b2..6b057078 100644 --- a/glib/test-dbus-glib.c +++ b/glib/test-dbus-glib.c @@ -30,8 +30,9 @@ main (int argc, char **argv) dbus_connection_setup_with_g_main (connection, NULL); - message = dbus_message_new_method_call (DBUS_MESSAGE_HELLO, - DBUS_SERVICE_DBUS); + message = dbus_message_new_method_call (DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, + "Hello", + DBUS_SERVICE_ORG_FREEDESKTOP_DBUS); dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error); @@ -42,7 +43,7 @@ main (int argc, char **argv) return 1; } - g_print ("reply name: %s\n", dbus_message_get_name (reply)); + g_print ("reply received\n"); g_main_loop_run (loop); diff --git a/glib/test-profile.c b/glib/test-profile.c index 852bd091..bd04dd9c 100644 --- a/glib/test-profile.c +++ b/glib/test-profile.c @@ -21,6 +21,11 @@ * */ +/* FIXME this test is wacky since both client and server keep + * sending each other method calls, but nobody sends + * a DBUS_MESSAGE_TYPE_METHOD_RETURN + */ + #include #include #include "dbus-glib.h" @@ -29,7 +34,9 @@ #define N_CLIENT_THREADS 1 #define N_ITERATIONS 1000 #define PAYLOAD_SIZE 30 -#define ECHO_MESSAGE "org.freedesktop.DBus.Test.EchoProfile" +#define ECHO_INTERFACE "org.freedekstop.EchoTest" +#define ECHO_METHOD "EchoProfile" + static const char *address; static unsigned char *payload; @@ -38,7 +45,7 @@ send_echo_message (DBusConnection *connection) { DBusMessage *message; - message = dbus_message_new_method_call (ECHO_MESSAGE, NULL); + message = dbus_message_new_method_call (ECHO_INTERFACE, ECHO_METHOD, NULL); dbus_message_append_args (message, DBUS_TYPE_STRING, "Hello World!", DBUS_TYPE_INT32, 123456, @@ -61,13 +68,15 @@ client_filter (DBusMessageHandler *handler, { int *iterations = user_data; - if (dbus_message_has_name (message, DBUS_MESSAGE_LOCAL_DISCONNECT)) + if (dbus_message_is_signal (message, + DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, + "Disconnected")) { g_printerr ("Client thread disconnected\n"); exit (1); } - else if (dbus_message_has_name (message, - ECHO_MESSAGE)) + else if (dbus_message_is_method_call (message, + ECHO_INTERFACE, ECHO_METHOD)) { *iterations += 1; if (*iterations >= N_ITERATIONS) @@ -139,13 +148,16 @@ server_filter (DBusMessageHandler *handler, DBusMessage *message, void *user_data) { - if (dbus_message_has_name (message, DBUS_MESSAGE_LOCAL_DISCONNECT)) + if (dbus_message_is_signal (message, + DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, + "Disconnected")) { g_printerr ("Server thread disconnected\n"); exit (1); } - else if (dbus_message_has_name (message, - ECHO_MESSAGE)) + else if (dbus_message_is_method_call (message, + ECHO_INTERFACE, + ECHO_METHOD)) { send_echo_message (connection); return DBUS_HANDLER_RESULT_HANDLED; diff --git a/glib/test-thread-client.c b/glib/test-thread-client.c index a3290b27..8a1e44cb 100644 --- a/glib/test-thread-client.c +++ b/glib/test-thread-client.c @@ -19,7 +19,8 @@ thread_func (gpointer data) while (1) { - message = dbus_message_new_method_call ("org.freedesktop.ThreadTest", NULL); + message = dbus_message_new_method_call ("org.freedesktop.ThreadTest", + "TestMethod", NULL); dbus_message_append_iter_init (message, &iter); diff --git a/glib/test-thread-server.c b/glib/test-thread-server.c index 3ad1f907..33652f8c 100644 --- a/glib/test-thread-server.c +++ b/glib/test-thread-server.c @@ -43,7 +43,8 @@ handle_test_message (DBusMessageHandler *handler, GString *counter_str; int i; - if (!dbus_message_has_name (message, "org.freedesktop.ThreadTest")) + if (!dbus_message_is_method_call (message, "org.freedesktop.ThreadTest", + "TestMethod")) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; dbus_message_iter_init (message, &iter); @@ -145,7 +146,8 @@ handle_disconnect (DBusMessageHandler *handler, DBusMessage *message, void *user_data) { - if (!dbus_message_has_name (message, DBUS_MESSAGE_LOCAL_DISCONNECT)) + if (!dbus_message_is_signal (message, DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, + "Disconnected")) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; g_print ("connection disconnected\n"); -- cgit From 8d38a2e2c5dc95de992c4d856ec1b0c0948bca3e Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Fri, 29 Aug 2003 01:05:00 +0000 Subject: 2003-08-28 Havoc Pennington purge DBusObjectID * dbus/dbus-connection.c: port to no ObjectID, create a DBusObjectTree, rename ObjectTree to ObjectPath in public API * dbus/dbus-connection.h (struct DBusObjectTreeVTable): delete everything except UnregisterFunction and MessageFunction * dbus/dbus-marshal.c: port away from DBusObjectID, add DBUS_TYPE_OBJECT_PATH * dbus/dbus-object-registry.[hc], dbus/dbus-object.[hc], dbus/dbus-objectid.[hc]: remove these, we are moving to path-based object IDs --- glib/dbus-gproxy.c | 4 ++-- glib/dbus-gproxy.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'glib') diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c index 36f9724c..01a6b4b9 100644 --- a/glib/dbus-gproxy.c +++ b/glib/dbus-gproxy.c @@ -35,7 +35,7 @@ struct DBusGProxy DBusConnection *connection; char *service; char *interface; - DBusObjectID object_id; + char *path; }; #define LOCK_PROXY(proxy) (g_static_mutex_lock (&(proxy)->lock)) @@ -248,7 +248,7 @@ dbus_gproxy_send (DBusGProxy *proxy, { /* FIXME */ } - if (!dbus_object_id_is_null (&proxy->object_id)) + if (proxy->path) { /* FIXME */ } diff --git a/glib/dbus-gproxy.h b/glib/dbus-gproxy.h index f40ce8a0..4e8f3f60 100644 --- a/glib/dbus-gproxy.h +++ b/glib/dbus-gproxy.h @@ -42,8 +42,8 @@ DBusGProxy* dbus_gproxy_new_for_service_owner (DBusConnection *connect const char *service_name, const char *interface_name, GError **error); -DBusGProxy* dbus_gproxy_new_for_object_id (DBusConnection *connection, - const DBusObjectID *object_id, +DBusGProxy* dbus_gproxy_new_for_object_path (DBusConnection *connection, + const char *path, const char *interface_name); DBusGProxy* dbus_gproxy_new_for_interface (DBusConnection *connection, const char *interface_name); -- cgit From ce969c6347b69180088c592e9184f05d0d3525c4 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sat, 30 Aug 2003 02:56:12 +0000 Subject: 2003-08-29 Havoc Pennington * dbus/dbus-object-tree.c: modify to allow overlapping paths to be registered (struct DBusObjectSubtree): shrink this a lot, since we may have a lot of them (_dbus_object_tree_free_all_unlocked): implement (_dbus_object_tree_dispatch_and_unlock): implement --- glib/dbus-gidl.c | 5 +---- glib/dbus-gidl.h | 10 +--------- 2 files changed, 2 insertions(+), 13 deletions(-) (limited to 'glib') diff --git a/glib/dbus-gidl.c b/glib/dbus-gidl.c index b6e0fb8c..c1a1f6dc 100644 --- a/glib/dbus-gidl.c +++ b/glib/dbus-gidl.c @@ -37,7 +37,6 @@ struct MethodInfo int refcount; GSList *args; char *name; - MethodStyle style; }; struct SignalInfo @@ -157,15 +156,13 @@ free_arg_list (GSList **args_p) } MethodInfo* -method_info_new (const char *name, - MethodStyle style) +method_info_new (const char *name) { MethodInfo *info; info = g_new0 (MethodInfo, 1); info->refcount = 1; info->name = g_strdup (name); - info->style = style; return info; } diff --git a/glib/dbus-gidl.h b/glib/dbus-gidl.h index c3c72d61..812e1866 100644 --- a/glib/dbus-gidl.h +++ b/glib/dbus-gidl.h @@ -40,13 +40,6 @@ typedef enum ARG_OUT } ArgDirection; -typedef enum -{ - METHOD_SYNC, - METHOD_ASYNC, - METHOD_CANCELLABLE -} MethodStyle; - InterfaceInfo* interface_info_new (const char *name); void interface_info_ref (InterfaceInfo *info); void interface_info_unref (InterfaceInfo *info); @@ -57,8 +50,7 @@ void interface_info_add_method (InterfaceInfo *info, void interface_info_add_signal (InterfaceInfo *info, SignalInfo *signal); -MethodInfo* method_info_new (const char *name, - MethodStyle style); +MethodInfo* method_info_new (const char *name); void method_info_ref (MethodInfo *info); void method_info_unref (MethodInfo *info); -- cgit From 5fd1e389e1c1c12ad4a55c2af6abdc8e7a2f6d41 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 31 Aug 2003 01:51:44 +0000 Subject: 2003-08-30 Havoc Pennington * test/data/valid-config-files/system.d/test.conf: change to root for the user so warnings don't get printed * dbus/dbus-message.c: add dbus_message_get_path, dbus_message_set_path * dbus/dbus-object-tree.c (do_test_dispatch): add test of dispatching to a path * dbus/dbus-string.c (_dbus_string_validate_path): add * dbus/dbus-marshal.c (_dbus_demarshal_object_path): implement (_dbus_marshal_object_path): implement * dbus/dbus-protocol.h (DBUS_HEADER_FIELD_PATH): new header field to contain the path to the target object (DBUS_HEADER_FIELD_SENDER_SERVICE): rename DBUS_HEADER_FIELD_SENDER to explicitly say it's the sender service --- glib/dbus-gidl.c | 6 ------ glib/dbus-gidl.h | 1 - glib/test-dbus-glib.c | 7 ++++--- glib/test-profile.c | 6 ++++-- glib/test-thread-client.c | 6 ++++-- 5 files changed, 12 insertions(+), 14 deletions(-) (limited to 'glib') diff --git a/glib/dbus-gidl.c b/glib/dbus-gidl.c index c1a1f6dc..d64e95a7 100644 --- a/glib/dbus-gidl.c +++ b/glib/dbus-gidl.c @@ -197,12 +197,6 @@ method_info_get_args (MethodInfo *info) return info->args; } -MethodStyle -method_info_get_style (MethodInfo *info) -{ - return info->style; -} - void method_info_add_arg (MethodInfo *info, ArgInfo *arg) diff --git a/glib/dbus-gidl.h b/glib/dbus-gidl.h index 812e1866..68649cf3 100644 --- a/glib/dbus-gidl.h +++ b/glib/dbus-gidl.h @@ -56,7 +56,6 @@ void method_info_unref (MethodInfo *info); const char* method_info_get_name (MethodInfo *info); GSList* method_info_get_args (MethodInfo *info); -MethodStyle method_info_get_style (MethodInfo *info); void method_info_add_arg (MethodInfo *info, ArgInfo *arg); diff --git a/glib/test-dbus-glib.c b/glib/test-dbus-glib.c index 6b057078..beda0a7a 100644 --- a/glib/test-dbus-glib.c +++ b/glib/test-dbus-glib.c @@ -30,9 +30,10 @@ main (int argc, char **argv) dbus_connection_setup_with_g_main (connection, NULL); - message = dbus_message_new_method_call (DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, - "Hello", - DBUS_SERVICE_ORG_FREEDESKTOP_DBUS); + message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, + DBUS_PATH_ORG_FREEDESKTOP_DBUS, + DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, + "Hello"); dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error); diff --git a/glib/test-profile.c b/glib/test-profile.c index bd04dd9c..3eac1618 100644 --- a/glib/test-profile.c +++ b/glib/test-profile.c @@ -34,7 +34,8 @@ #define N_CLIENT_THREADS 1 #define N_ITERATIONS 1000 #define PAYLOAD_SIZE 30 -#define ECHO_INTERFACE "org.freedekstop.EchoTest" +#define ECHO_PATH "/org/freedesktop/EchoTest" +#define ECHO_INTERFACE "org.freedesktop.EchoTest" #define ECHO_METHOD "EchoProfile" static const char *address; @@ -45,7 +46,8 @@ send_echo_message (DBusConnection *connection) { DBusMessage *message; - message = dbus_message_new_method_call (ECHO_INTERFACE, ECHO_METHOD, NULL); + message = dbus_message_new_method_call (NULL, ECHO_PATH, + ECHO_INTERFACE, ECHO_METHOD); dbus_message_append_args (message, DBUS_TYPE_STRING, "Hello World!", DBUS_TYPE_INT32, 123456, diff --git a/glib/test-thread-client.c b/glib/test-thread-client.c index 8a1e44cb..d51d4e6a 100644 --- a/glib/test-thread-client.c +++ b/glib/test-thread-client.c @@ -19,8 +19,10 @@ thread_func (gpointer data) while (1) { - message = dbus_message_new_method_call ("org.freedesktop.ThreadTest", - "TestMethod", NULL); + message = dbus_message_new_method_call (NULL, + "/org/freedesktop/ThreadTest", + "org.freedesktop.ThreadTest", + "TestMethod"); dbus_message_append_iter_init (message, &iter); -- cgit From 1dd3f1788f1b4c9af2f4fa744abdb7892d0a14b9 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 31 Aug 2003 03:25:24 +0000 Subject: 2003-08-30 Havoc Pennington * dbus/dbus-connection.c: purge DBusMessageHandler * dbus/dbus-message-handler.c: remove DBusMessageHandler, just use callbacks everywhere --- glib/test-profile.c | 23 +++++---------------- glib/test-thread-server.c | 52 +++++------------------------------------------ 2 files changed, 10 insertions(+), 65 deletions(-) (limited to 'glib') diff --git a/glib/test-profile.c b/glib/test-profile.c index 3eac1618..6d9d8e7f 100644 --- a/glib/test-profile.c +++ b/glib/test-profile.c @@ -63,8 +63,7 @@ send_echo_message (DBusConnection *connection) } static DBusHandlerResult -client_filter (DBusMessageHandler *handler, - DBusConnection *connection, +client_filter (DBusConnection *connection, DBusMessage *message, void *user_data) { @@ -99,7 +98,6 @@ thread_func (void *data) DBusError error; GMainContext *context; GMainLoop *loop; - DBusMessageHandler *handler; DBusConnection *connection; int iterations; @@ -116,14 +114,9 @@ thread_func (void *data) iterations = 1; - handler = dbus_message_handler_new (client_filter, - &iterations, NULL); - if (!dbus_connection_add_filter (connection, - handler)) + client_filter, &iterations, NULL)) g_error ("no memory"); - - /* FIXME we leak the handler */ context = g_main_context_new (); loop = g_main_loop_new (context, FALSE); @@ -145,8 +138,7 @@ thread_func (void *data) } static DBusHandlerResult -server_filter (DBusMessageHandler *handler, - DBusConnection *connection, +server_filter (DBusConnection *connection, DBusMessage *message, void *user_data) { @@ -172,17 +164,12 @@ static void new_connection_callback (DBusServer *server, DBusConnection *new_connection, void *user_data) -{ - DBusMessageHandler *handler; - +{ dbus_connection_ref (new_connection); dbus_connection_setup_with_g_main (new_connection, NULL); - - handler = dbus_message_handler_new (server_filter, - NULL, NULL); if (!dbus_connection_add_filter (new_connection, - handler)) + server_filter, NULL, NULL)) g_error ("no memory"); diff --git a/glib/test-thread-server.c b/glib/test-thread-server.c index 33652f8c..8898ca7f 100644 --- a/glib/test-thread-server.c +++ b/glib/test-thread-server.c @@ -25,13 +25,8 @@ thread_test_data_free (ThreadTestData *data) g_free (data); } -static DBusMessageHandler *disconnect_handler; -static DBusMessageHandler *filter_handler; -static dbus_int32_t handler_slot = -1; - static DBusHandlerResult -handle_test_message (DBusMessageHandler *handler, - DBusConnection *connection, +filter_test_message (DBusConnection *connection, DBusMessage *message, void *user_data) { @@ -132,17 +127,7 @@ handle_test_message (DBusMessageHandler *handler, } static DBusHandlerResult -handle_filter (DBusMessageHandler *handler, - DBusConnection *connection, - DBusMessage *message, - void *user_data) -{ - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static DBusHandlerResult -handle_disconnect (DBusMessageHandler *handler, - DBusConnection *connection, +filter_disconnect (DBusConnection *connection, DBusMessage *message, void *user_data) { @@ -161,7 +146,6 @@ new_connection_callback (DBusServer *server, DBusConnection *new_connection, void *user_data) { - DBusMessageHandler *test_message_handler; ThreadTestData * data; g_print ("new_connection_callback\n"); @@ -171,26 +155,13 @@ new_connection_callback (DBusServer *server, data = thread_test_data_new (); - test_message_handler = - dbus_message_handler_new (handle_test_message, - data, (DBusFreeFunction)thread_test_data_free); - if (!dbus_connection_add_filter (new_connection, - test_message_handler)) - goto nomem; - - if (!dbus_connection_set_data (new_connection, - handler_slot, - test_message_handler, - (DBusFreeFunction)dbus_message_handler_unref)) + filter_test_message, data, + (DBusFreeFunction) thread_test_data_free)) goto nomem; if (!dbus_connection_add_filter (new_connection, - disconnect_handler)) - goto nomem; - - if (!dbus_connection_add_filter (new_connection, - filter_handler)) + filter_disconnect, NULL, NULL)) goto nomem; return; @@ -224,19 +195,6 @@ main (int argc, char *argv[]) dbus_error_free (&error); return 1; } - - if (!dbus_connection_allocate_data_slot (&handler_slot)) - g_error ("no memory for data slot"); - - filter_handler = - dbus_message_handler_new (handle_filter, NULL, NULL); - if (filter_handler == NULL) - g_error ("no memory for handler"); - - disconnect_handler = - dbus_message_handler_new (handle_disconnect, NULL, NULL); - if (disconnect_handler == NULL) - g_error ("no memory for handler"); dbus_server_set_new_connection_function (server, new_connection_callback, -- cgit From 7b4ac5de11d90e9f7048f057d70d3da5104388b6 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Mon, 1 Sep 2003 18:02:06 +0000 Subject: 2003-09-01 Havoc Pennington * glib/Makefile.am: rearrange a bunch of files and get "make check" framework set up --- glib/Makefile.am | 30 ++++++++++-- glib/dbus-compiler-main.c | 48 ------------------ glib/dbus-glib-tool.c | 77 +++++++++++++++++++++++++++++ glib/dbus-gmain.c | 19 +++++++- glib/dbus-gparser.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++ glib/dbus-gparser.h | 59 ++++++++++++++++++++++ 6 files changed, 300 insertions(+), 54 deletions(-) delete mode 100644 glib/dbus-compiler-main.c create mode 100644 glib/dbus-glib-tool.c create mode 100644 glib/dbus-gparser.c create mode 100644 glib/dbus-gparser.h (limited to 'glib') diff --git a/glib/Makefile.am b/glib/Makefile.am index 8cc09eb7..3d67db2f 100644 --- a/glib/Makefile.am +++ b/glib/Makefile.am @@ -11,18 +11,24 @@ dbusinclude_HEADERS= \ libdbus_glib_1_la_SOURCES = \ dbus-gmain.c \ dbus-gproxy.c \ + dbus-gtest.c \ + dbus-gtest.h \ dbus-gthread.c libdbus_glib_1_la_LIBADD= $(DBUS_GLIB_LIBS) $(top_builddir)/dbus/libdbus-1.la -bin_PROGRAMS=dbus-glib-compiler +bin_PROGRAMS=dbus-glib-tool -dbus_glib_compiler_SOURCES = \ +dbus_glib_tool_SOURCES = \ dbus-gidl.c \ dbus-gidl.h \ - dbus-compiler-main.c + dbus-glib-tool.c \ + dbus-gparser.c \ + dbus-gparser.h \ + dbus-gtool-test.h -dbus_glib_compiler_LDADD= libdbus-glib-1.la $(DBUS_GLIB_LIBS) $(top_builddir)/dbus/libdbus-1.la + +dbus_glib_tool_LDADD= libdbus-glib-1.la $(DBUS_GLIB_LIBS) $(top_builddir)/dbus/libdbus-1.la if DBUS_BUILD_TESTS @@ -42,15 +48,29 @@ test_thread_client_SOURCES= \ test_thread_client_LDADD= $(DBUS_GLIB_THREADS_LIBS) $(top_builddir)/glib/libdbus-glib-1.la endif -noinst_PROGRAMS= test-dbus-glib $(THREAD_APPS) +## we use noinst_PROGRAMS not check_PROGRAMS for TESTS so that we +## build even when not doing "make check" +noinst_PROGRAMS= $(TESTS) test-dbus-glib $(THREAD_APPS) test_dbus_glib_SOURCES= \ test-dbus-glib.c test_dbus_glib_LDADD= $(top_builddir)/glib/libdbus-glib-1.la +## note that TESTS has special meaning (stuff to use in make check) +## so if adding tests not to be run in make check, don't add them to +## TESTS +TESTS_ENVIRONMENT=DBUS_TEST_DATA=$(top_builddir)/test/data DBUS_TEST_HOMEDIR=$(top_builddir)/dbus +TESTS=dbus-glib-test + +dbus_glib_test_SOURCES= \ + dbus-gtest-main.c + +dbus_glib_test_LDADD= $(top_builddir)/glib/libdbus-glib-1.la + else ### not building tests +TESTS= if HAVE_GLIB_THREADS noinst_PROGRAMS=test-profile diff --git a/glib/dbus-compiler-main.c b/glib/dbus-compiler-main.c deleted file mode 100644 index d8bf7bde..00000000 --- a/glib/dbus-compiler-main.c +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ -/* dbus-compiler-main.c main() for GLib stubs/skels generator - * - * Copyright (C) 2003 Red Hat, Inc. - * - * Licensed under the Academic Free License version 1.2 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "dbus-gidl.h" - -int -main (int argc, char **argv) -{ - - - return 0; -} - -#ifdef DBUS_BUILD_TESTS - -/** - * @ingroup DBusGCompiler - * Unit test for GLib stubs/skels compiler - * @returns #TRUE on success. - */ -dbus_bool_t -_dbus_gcompiler_test (void) -{ - - return TRUE; -} - -#endif /* DBUS_BUILD_TESTS */ diff --git a/glib/dbus-glib-tool.c b/glib/dbus-glib-tool.c new file mode 100644 index 00000000..aaf133d4 --- /dev/null +++ b/glib/dbus-glib-tool.c @@ -0,0 +1,77 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-compiler-main.c main() for GLib stubs/skels generator + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "dbus-gidl.h" +#include + +#ifdef DBUS_BUILD_TESTS +static void run_all_tests (const char *test_data_dir); +#endif + +int +main (int argc, char **argv) +{ + setlocale(LC_ALL, ""); + + return 0; +} + +#ifdef DBUS_BUILD_TESTS +static void +test_die (const char *failure) +{ + fprintf (stderr, "Unit test failed: %s\n", failure); + exit (1); +} + +static void +run_all_tests (const char *test_data_dir) +{ + if (test_data_dir == NULL) + test_data_dir = _dbus_getenv ("DBUS_TEST_DATA"); + + if (test_data_dir != NULL) + printf ("Test data in %s\n", test_data_dir); + else + printf ("No test data!\n"); + + printf ("%s: running gtool tests\n", "dbus-glib-tool"); + if (!_dbus_gtool_test (test_data_dir)) + test_die ("gtool"); + + printf ("%s: completed successfully\n", "dbus-glib-test"); +} + +/** + * @ingroup DBusGTool + * Unit test for GLib utility tool + * @returns #TRUE on success. + */ +dbus_bool_t +_dbus_gtool_test (const char *test_data_dir) +{ + + return TRUE; +} + +#endif /* DBUS_BUILD_TESTS */ diff --git a/glib/dbus-gmain.c b/glib/dbus-gmain.c index 9b14049d..36c6c6b4 100644 --- a/glib/dbus-gmain.c +++ b/glib/dbus-gmain.c @@ -21,8 +21,9 @@ * */ +#include #include "dbus-glib.h" -#include +#include "dbus-gtest.h" /** * @defgroup DBusGLib GLib bindings @@ -491,3 +492,19 @@ dbus_server_setup_with_g_main (DBusServer *server, } /** @} */ /* end of public API */ + +#ifdef DBUS_BUILD_TESTS + +/** + * @ingroup DBusGLibInternals + * Unit test for GLib main loop integration + * @returns #TRUE on success. + */ +dbus_bool_t +_dbus_gmain_test (const char *test_data_dir) +{ + + return TRUE; +} + +#endif /* DBUS_BUILD_TESTS */ diff --git a/glib/dbus-gparser.c b/glib/dbus-gparser.c new file mode 100644 index 00000000..6fea4abc --- /dev/null +++ b/glib/dbus-gparser.c @@ -0,0 +1,121 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-gparser.c parse DBus description files + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include "dbus-gparser.h" +#include "dbus-gidl.h" + +struct Parser +{ + int refcount; + +}; + +Parser* +parser_new (void) +{ + Parser *parser; + + parser = g_new0 (Parser, 1); + + parser->refcount = 1; + + return parser; +} + +void +parser_ref (Parser *parser) +{ + parser->refcount += 1; +} + +void +parser_unref (Parser *parser) +{ + parser->refcount -= 1; + if (parser->refcount == 0) + { + + + g_free (parser); + } +} + +gboolean +parser_check_doctype (Parser *parser, + const char *doctype, + GError **error) +{ + g_return_val_if_fail (error == NULL || *error == NULL); + + if (strcmp (doctype, "dbus_description") != 0) + { + g_set_error (error, + G_MARKUP_ERROR_PARSE, + "D-BUS description file has the wrong document type %s, use dbus_description", + doctype); + return FALSE; + } + else + return TRUE; +} + +gboolean +parser_start_element (Parser *parser, + const char *element_name, + const char **attribute_names, + const char **attribute_values, + GError **error) +{ + g_return_val_if_fail (error == NULL || *error == NULL); + + return TRUE; +} + +gboolean +parser_end_element (Parser *parser, + const char *element_name, + GError **error) +{ + g_return_val_if_fail (error == NULL || *error == NULL); + + return TRUE; +} + +gboolean +parser_content (Parser *parser, + const char *content, + int len, + GError **error) +{ + g_return_val_if_fail (error == NULL || *error == NULL); + + return TRUE; +} + +gboolean +parser_finished (Parser *parser, + GError **error) +{ + g_return_val_if_fail (error == NULL || *error == NULL); + + return TRUE; +} diff --git a/glib/dbus-gparser.h b/glib/dbus-gparser.h new file mode 100644 index 00000000..01339fbf --- /dev/null +++ b/glib/dbus-gparser.h @@ -0,0 +1,59 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-gparser.h parse DBus description files + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef DBUS_GLIB_PARSER_H +#define DBUS_GLIB_PARSER_H + +#include +#include + +G_BEGIN_DECLS + + +typedef struct Parser Parser; + +Parser* parser_new (void); +void parser_ref (Parser *parser); +void parser_unref (Parser *parser); +gboolean parser_check_doctype (Parser *parser, + const char *doctype, + GError **error); +gboolean parser_start_element (Parser *parser, + const char *element_name, + const char **attribute_names, + const char **attribute_values, + GError **error); +gboolean parser_end_element (Parser *parser, + const char *element_name, + GError **error); +gboolean parser_content (Parser *parser, + const char *content, + int len, + GError **error); +gboolean parser_finished (Parser *parser, + GError **error); + + + +G_END_DECLS + +#endif /* DBUS_GLIB_GPARSER_H */ -- cgit From d021cfae6695f0f44102edf758abfc42e2f3c093 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 3 Sep 2003 02:08:25 +0000 Subject: 2003-09-01 Havoc Pennington * glib/dbus-gparser.c: implement * glib/dbus-gobject.c: start implementing skeletons support * configure.in: when disabling checks/assert, also define G_DISABLE_ASSERT and G_DISABLE_CHECKS --- glib/Makefile.am | 6 +- glib/dbus-gidl.c | 90 +++++- glib/dbus-gidl.h | 10 + glib/dbus-glib.h | 26 +- glib/dbus-gloader-expat.c | 254 +++++++++++++++ glib/dbus-gobject.c | 780 ++++++++++++++++++++++++++++++++++++++++++++++ glib/dbus-gparser.c | 549 +++++++++++++++++++++++++++++++- glib/dbus-gparser.h | 8 +- 8 files changed, 1709 insertions(+), 14 deletions(-) create mode 100644 glib/dbus-gloader-expat.c create mode 100644 glib/dbus-gobject.c (limited to 'glib') diff --git a/glib/Makefile.am b/glib/Makefile.am index 3d67db2f..f3b43ed3 100644 --- a/glib/Makefile.am +++ b/glib/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_GLIB_CFLAGS) -DDBUS_COMPILATION=1 +INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_GLIB_CFLAGS) $(DBUS_GLIB_TOOL_CFLAGS) -DDBUS_COMPILATION=1 dbusincludedir=$(includedir)/dbus-1.0/dbus @@ -10,6 +10,7 @@ dbusinclude_HEADERS= \ libdbus_glib_1_la_SOURCES = \ dbus-gmain.c \ + dbus-gobject.c \ dbus-gproxy.c \ dbus-gtest.c \ dbus-gtest.h \ @@ -23,12 +24,13 @@ dbus_glib_tool_SOURCES = \ dbus-gidl.c \ dbus-gidl.h \ dbus-glib-tool.c \ + dbus-gloader-expat.c \ dbus-gparser.c \ dbus-gparser.h \ dbus-gtool-test.h -dbus_glib_tool_LDADD= libdbus-glib-1.la $(DBUS_GLIB_LIBS) $(top_builddir)/dbus/libdbus-1.la +dbus_glib_tool_LDADD= $(DBUS_GLIB_TOOL_LIBS) libdbus-glib-1.la $(top_builddir)/dbus/libdbus-1.la if DBUS_BUILD_TESTS diff --git a/glib/dbus-gidl.c b/glib/dbus-gidl.c index d64e95a7..12468abb 100644 --- a/glib/dbus-gidl.c +++ b/glib/dbus-gidl.c @@ -24,6 +24,13 @@ #include "dbus-gidl.h" +struct NodeInfo +{ + int refcount; + char *name; + GSList *interfaces; +}; + struct InterfaceInfo { int refcount; @@ -54,6 +61,20 @@ struct ArgInfo ArgDirection direction; }; +static void +free_interface_list (GSList **interfaces_p) +{ + GSList *tmp; + tmp = *interfaces_p; + while (tmp != NULL) + { + interface_info_unref (tmp->data); + tmp = tmp->next; + } + g_slist_free (*interfaces_p); + *interfaces_p = NULL; +} + static void free_method_list (GSList **methods_p) { @@ -82,6 +103,59 @@ free_signal_list (GSList **signals_p) *signals_p = NULL; } +NodeInfo* +node_info_new (const char *name) +{ + NodeInfo *info; + + /* name can be NULL */ + + info = g_new0 (NodeInfo, 1); + info->refcount = 1; + info->name = g_strdup (name); + + return info; +} + +void +node_info_ref (NodeInfo *info) +{ + info->refcount += 1; +} + +void +node_info_unref (NodeInfo *info) +{ + info->refcount -= 1; + if (info->refcount == 0) + { + free_interface_list (&info->interfaces); + g_free (info->name); + g_free (info); + } +} + +const char* +node_info_get_name (NodeInfo *info) +{ + return info->name; +} + +GSList* +node_info_get_interfaces (NodeInfo *info) +{ + return info->interfaces; +} + +void +node_info_add_interface (NodeInfo *info, + InterfaceInfo *interface) +{ + interface_info_ref (interface); + info->interfaces = g_slist_append (info->interfaces, interface); +} + + InterfaceInfo* interface_info_new (const char *name) { @@ -90,7 +164,7 @@ interface_info_new (const char *name) info = g_new0 (InterfaceInfo, 1); info->refcount = 1; info->name = g_strdup (name); - + return info; } @@ -113,6 +187,12 @@ interface_info_unref (InterfaceInfo *info) } } +const char* +interface_info_get_name (InterfaceInfo *info) +{ + return info->name; +} + GSList* interface_info_get_methods (InterfaceInfo *info) { @@ -163,7 +243,7 @@ method_info_new (const char *name) info = g_new0 (MethodInfo, 1); info->refcount = 1; info->name = g_strdup (name); - + return info; } @@ -213,7 +293,7 @@ signal_info_new (const char *name) info = g_new0 (SignalInfo, 1); info->refcount = 1; info->name = g_strdup (name); - + return info; } @@ -264,10 +344,12 @@ arg_info_new (const char *name, info = g_new0 (ArgInfo, 1); info->refcount = 1; + + /* name can be NULL */ info->name = g_strdup (name); info->direction = direction; info->type = type; - + return info; } diff --git a/glib/dbus-gidl.h b/glib/dbus-gidl.h index 68649cf3..6e4e207a 100644 --- a/glib/dbus-gidl.h +++ b/glib/dbus-gidl.h @@ -29,6 +29,7 @@ G_BEGIN_DECLS +typedef struct NodeInfo NodeInfo; typedef struct InterfaceInfo InterfaceInfo; typedef struct MethodInfo MethodInfo; typedef struct SignalInfo SignalInfo; @@ -40,9 +41,18 @@ typedef enum ARG_OUT } ArgDirection; +NodeInfo* node_info_new (const char *name); +void node_info_ref (NodeInfo *info); +void node_info_unref (NodeInfo *info); +const char* node_info_get_name (NodeInfo *info); +GSList* node_info_get_interfaces (NodeInfo *info); +void node_info_add_interface (NodeInfo *info, + InterfaceInfo *interface); + InterfaceInfo* interface_info_new (const char *name); void interface_info_ref (InterfaceInfo *info); void interface_info_unref (InterfaceInfo *info); +const char* interface_info_get_name (InterfaceInfo *info); GSList* interface_info_get_methods (InterfaceInfo *info); GSList* interface_info_get_signals (InterfaceInfo *info); void interface_info_add_method (InterfaceInfo *info, diff --git a/glib/dbus-glib.h b/glib/dbus-glib.h index 7ca22417..3a87dec2 100644 --- a/glib/dbus-glib.h +++ b/glib/dbus-glib.h @@ -24,7 +24,7 @@ #define DBUS_GLIB_H #include -#include +#include G_BEGIN_DECLS @@ -36,6 +36,30 @@ void dbus_connection_setup_with_g_main (DBusConnection *connection, void dbus_server_setup_with_g_main (DBusServer *server, GMainContext *context); +typedef struct DBusGObjectInfo DBusGObjectInfo; +typedef struct DBusGMethodInfo DBusGMethodInfo; + +struct DBusGMethodInfo +{ + GCallback function; + DBusHandleMessageFunction marshaller; + int data_offset; +}; + +struct DBusGObjectInfo +{ + const DBusGMethodInfo *infos; + const unsigned char *data; + void *dbus_internal_padding1; + void *dbus_internal_padding2; +}; + +void dbus_gobject_class_install_info (GObjectClass *object_class, + const DBusGObjectInfo *info); +void dbus_connection_register_gobject (DBusConnection *connection, + const char *at_path, + GObject *object); + #undef DBUS_INSIDE_DBUS_GLIB_H G_END_DECLS diff --git a/glib/dbus-gloader-expat.c b/glib/dbus-gloader-expat.c new file mode 100644 index 00000000..050d3532 --- /dev/null +++ b/glib/dbus-gloader-expat.c @@ -0,0 +1,254 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-gloader-expat.c expat XML loader + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "dbus-gparser.h" +#include + +static void* +expat_g_malloc (size_t sz) +{ + return g_malloc (sz); +} + +static void* +expat_g_realloc (void *mem, size_t sz) +{ + return g_realloc (mem, sz); +} + +static XML_Memory_Handling_Suite memsuite = +{ + expat_g_malloc, + expat_g_realloc, + g_free +}; + +typedef struct +{ + Parser *parser; + const char *filename; + GString *content; + GError **error; + gboolean failed; +} ExpatParseContext; + +static dbus_bool_t +process_content (ExpatParseContext *context) +{ + if (context->failed) + return FALSE; + + if (context->content->len > 0) + { + if (!parser_content (context->parser, + context->content->str, + context->content->len, + context->error)) + { + context->failed = TRUE; + return FALSE; + } + g_string_set_size (context->content, 0); + } + + return TRUE; +} + +static void +expat_StartElementHandler (void *userData, + const XML_Char *name, + const XML_Char **atts) +{ + ExpatParseContext *context = userData; + int i; + char **names; + char **values; + + /* Expat seems to suck and can't abort the parse if we + * throw an error. Expat 2.0 is supposed to fix this. + */ + if (context->failed) + return; + + if (!process_content (context)) + return; + + /* "atts" is key, value, key, value, NULL */ + for (i = 0; atts[i] != NULL; ++i) + ; /* nothing */ + + g_assert (i % 2 == 0); + names = g_new0 (char *, i / 2 + 1); + values = g_new0 (char *, i / 2 + 1); + + i = 0; + while (atts[i] != NULL) + { + g_assert (i % 2 == 0); + names [i / 2] = (char*) atts[i]; + values[i / 2] = (char*) atts[i+1]; + + i += 2; + } + + if (!parser_start_element (context->parser, + name, + (const char **) names, + (const char **) values, + context->error)) + { + g_free (names); + g_free (values); + context->failed = TRUE; + return; + } + + g_free (names); + g_free (values); +} + +static void +expat_EndElementHandler (void *userData, + const XML_Char *name) +{ + ExpatParseContext *context = userData; + + if (!process_content (context)) + return; + + if (!parser_end_element (context->parser, + name, + context->error)) + { + context->failed = TRUE; + return; + } +} + +/* s is not 0 terminated. */ +static void +expat_CharacterDataHandler (void *userData, + const XML_Char *s, + int len) +{ + ExpatParseContext *context = userData; + + if (context->failed) + return; + + g_string_append_len (context->content, + s, len); +} + +Parser* +description_load_from_file (const char *filename, + GError **error) +{ + char *contents; + gsize len; + Parser *parser; + + contents = NULL; + if (!g_file_get_contents (filename, &contents, &len, error)) + return NULL; + + parser = description_load_from_string (contents, len, error); + g_free (contents); + + return parser; +} + +Parser* +description_load_from_string (const char *str, + int len, + GError **error) +{ + XML_Parser expat; + ExpatParseContext context; + + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + expat = NULL; + context.parser = NULL; + context.error = error; + context.failed = FALSE; + + expat = XML_ParserCreate_MM ("UTF-8", &memsuite, NULL); + if (expat == NULL) + g_error ("No memory to create XML parser\n"); + + context.parser = parser_new (); + context.content = g_string_new (NULL); + + XML_SetUserData (expat, &context); + XML_SetElementHandler (expat, + expat_StartElementHandler, + expat_EndElementHandler); + XML_SetCharacterDataHandler (expat, + expat_CharacterDataHandler); + + if (!XML_Parse (expat, str, len, TRUE)) + { + if (context.error != NULL && + *context.error == NULL) + { + enum XML_Error e; + + e = XML_GetErrorCode (expat); + if (e == XML_ERROR_NO_MEMORY) + g_error ("Not enough memory to parse XML document"); + else + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + "Error in D-BUS description XML, line %d, column %d: %s\n", + XML_GetCurrentLineNumber (expat), + XML_GetCurrentColumnNumber (expat), + XML_ErrorString (e)); + } + + goto failed; + } + + if (context.failed) + goto failed; + + if (!parser_finished (context.parser, error)) + goto failed; + + XML_ParserFree (expat); + g_string_free (context.content, TRUE); + + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + return context.parser; + + failed: + g_return_val_if_fail (error == NULL || *error != NULL, NULL); + + g_string_free (context.content, TRUE); + if (expat) + XML_ParserFree (expat); + if (context.parser) + parser_unref (context.parser); + return NULL; +} diff --git a/glib/dbus-gobject.c b/glib/dbus-gobject.c new file mode 100644 index 00000000..aa53265b --- /dev/null +++ b/glib/dbus-gobject.c @@ -0,0 +1,780 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-gobject.c Exporting a GObject remotely + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include "dbus-glib.h" +#include "dbus-gtest.h" +#include + +/** + * @addtogroup DBusGLibInternals + * @{ + */ + +static GStaticMutex info_hash_mutex = G_STATIC_MUTEX_INIT; +static GHashTable *info_hash = NULL; + +static char* +javacaps_to_uscore (const char *caps) +{ + const char *p; + GString *str; + + str = g_string_new (NULL); + p = caps; + while (*p) + { + if (g_ascii_isupper (*p)) + { + if (str->len > 0 && + (str->len < 2 || str->str[str->len-2] != '_')) + g_string_append_c (str, '_'); + g_string_append_c (str, g_ascii_tolower (*p)); + } + else + { + g_string_append_c (str, *p); + } + ++p; + } + + return g_string_free (str, FALSE); +} + +static char* +uscore_to_javacaps (const char *uscore) +{ + const char *p; + GString *str; + gboolean last_was_uscore; + + last_was_uscore = TRUE; + + str = g_string_new (NULL); + p = uscore; + while (*p) + { + if (*p == '-' || *p == '_') + { + last_was_uscore = TRUE; + } + else + { + if (last_was_uscore) + { + g_string_append_c (str, g_ascii_toupper (*p)); + last_was_uscore = FALSE; + } + else + g_string_append_c (str, *p); + } + ++p; + } + + return g_string_free (str, FALSE); +} + +static void +gobject_unregister_function (DBusConnection *connection, + void *user_data) +{ + GObject *object; + + object = G_OBJECT (user_data); + + +} + +static int +gtype_to_dbus_type (GType type) +{ + switch (type) + { + case G_TYPE_CHAR: + case G_TYPE_UCHAR: + return DBUS_TYPE_BYTE; + + case G_TYPE_BOOLEAN: + return DBUS_TYPE_BOOLEAN; + + /* long gets cut to 32 bits so the remote API is consistent + * on all architectures + */ + + case G_TYPE_LONG: + case G_TYPE_INT: + return DBUS_TYPE_INT32; + case G_TYPE_ULONG: + case G_TYPE_UINT: + return DBUS_TYPE_UINT32; + + case G_TYPE_INT64: + return DBUS_TYPE_INT64; + + case G_TYPE_UINT64: + return DBUS_TYPE_UINT64; + + case G_TYPE_FLOAT: + case G_TYPE_DOUBLE: + return DBUS_TYPE_DOUBLE; + + case G_TYPE_STRING: + return DBUS_TYPE_STRING; + + default: + return DBUS_TYPE_INVALID; + } +} + +static const char * +dbus_type_to_string (int type) +{ + switch (type) + { + case DBUS_TYPE_INVALID: + return "invalid"; + case DBUS_TYPE_NIL: + return "nil"; + case DBUS_TYPE_BOOLEAN: + return "boolean"; + case DBUS_TYPE_INT32: + return "int32"; + case DBUS_TYPE_UINT32: + return "uint32"; + case DBUS_TYPE_DOUBLE: + return "double"; + case DBUS_TYPE_STRING: + return "string"; + case DBUS_TYPE_NAMED: + return "named"; + case DBUS_TYPE_ARRAY: + return "array"; + case DBUS_TYPE_DICT: + return "dict"; + default: + return "unknown"; + } +} + +static DBusHandlerResult +handle_introspect (DBusConnection *connection, + DBusMessage *message, + GObject *object) +{ + GString *xml; + GParamSpec **specs; + unsigned int n_specs; + unsigned int i; + GType last_type; + DBusMessage *ret; + + xml = g_string_new (NULL); + + g_string_append (xml, "\n"); + + last_type = G_TYPE_INVALID; + + specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), + &n_specs); + + i = 0; + while (i < n_specs) + { + GParamSpec *spec = specs[i]; + gboolean can_set; + gboolean can_get; + char *s; + int dbus_type; + + dbus_type = gtype_to_dbus_type (G_PARAM_SPEC_VALUE_TYPE (spec)); + if (dbus_type == DBUS_TYPE_INVALID) + goto next; + + if (spec->owner_type != last_type) + { + if (last_type != G_TYPE_INVALID) + g_string_append (xml, " \n"); + + + /* FIXME what should the namespace on the interface be in + * general? should people be able to set it for their + * objects? + */ + + g_string_append (xml, " owner_type)); + g_string_append (xml, "\">\n"); + + last_type = spec->owner_type; + } + + can_set = ((spec->flags & G_PARAM_WRITABLE) != 0 && + (spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0); + + can_get = (spec->flags & G_PARAM_READABLE) != 0; + + s = uscore_to_javacaps (spec->name); + + if (can_set) + { + g_string_append (xml, " \n"); + + g_string_append (xml, " \n"); + } + + if (can_get) + { + g_string_append (xml, " \n"); + + g_string_append (xml, " \n"); + } + + g_free (s); + + next: + ++i; + } + + if (last_type != G_TYPE_INVALID) + g_string_append (xml, " \n"); + + g_free (specs); + + /* Close the XML, and send it to the requesting app */ + + g_string_append (xml, "\n"); + + ret = dbus_message_new_method_return (message); + if (ret == NULL) + g_error ("out of memory"); + + dbus_message_append_args (message, + DBUS_TYPE_STRING, xml->str, + DBUS_TYPE_INVALID); + + dbus_connection_send (connection, message, NULL); + dbus_message_unref (message); + + g_string_free (xml, TRUE); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusMessage* +set_object_property (DBusConnection *connection, + DBusMessage *message, + GObject *object, + GParamSpec *pspec) +{ + GValue value; + DBusMessageIter iter; + int type; + gboolean can_set; + DBusMessage *ret; + + dbus_message_iter_init (message, &iter); + type = dbus_message_get_type (message); + + can_set = TRUE; + switch (type) + { + case DBUS_TYPE_BYTE: + { + unsigned char b; + + b = dbus_message_iter_get_byte (&iter); + + g_value_init (&value, G_TYPE_UCHAR); + + g_value_set_uchar (&value, b); + } + break; + case DBUS_TYPE_BOOLEAN: + { + gboolean b; + + b = dbus_message_iter_get_boolean (&iter); + + g_value_init (&value, G_TYPE_BOOLEAN); + + g_value_set_boolean (&value, b); + } + break; + case DBUS_TYPE_INT32: + { + gint32 i; + + i = dbus_message_iter_get_int32 (&iter); + + g_value_init (&value, G_TYPE_INT); + + g_value_set_int (&value, i); + } + break; + case DBUS_TYPE_UINT32: + { + guint32 i; + + i = dbus_message_iter_get_uint32 (&iter); + + g_value_init (&value, G_TYPE_UINT); + + g_value_set_uint (&value, i); + } + break; + case DBUS_TYPE_INT64: + { + gint64 i; + + i = dbus_message_iter_get_int64 (&iter); + + g_value_init (&value, G_TYPE_INT64); + + g_value_set_int64 (&value, i); + } + break; + case DBUS_TYPE_UINT64: + { + guint64 i; + + i = dbus_message_iter_get_uint64 (&iter); + + g_value_init (&value, G_TYPE_UINT64); + + g_value_set_uint64 (&value, i); + } + break; + case DBUS_TYPE_DOUBLE: + { + double d; + + d = dbus_message_iter_get_double (&iter); + + g_value_init (&value, G_TYPE_DOUBLE); + + g_value_set_double (&value, d); + } + break; + case DBUS_TYPE_STRING: + { + char *s; + + /* FIXME use a const string accessor */ + + s = dbus_message_iter_get_string (&iter); + + g_value_init (&value, G_TYPE_STRING); + + g_value_set_string (&value, s); + + g_free (s); + } + break; + + /* FIXME array and other types, especially byte array + * converted to G_TYPE_STRING + */ + + default: + can_set = FALSE; + break; + } + + /* The g_object_set_property() will transform some types, e.g. it + * will let you use a uchar to set an int property etc. Note that + * any error in value range or value conversion will just + * g_warning(). These GObject skels are not for secure applications. + */ + + if (can_set) + { + g_object_set_property (object, + pspec->name, + &value); + + ret = dbus_message_new_method_return (message); + if (ret == NULL) + g_error ("out of memory"); + + g_value_unset (&value); + } + else + { + ret = dbus_message_new_error (message, + DBUS_ERROR_INVALID_ARGS, + "Argument's D-BUS type can't be converted to a GType"); + if (ret == NULL) + g_error ("out of memory"); + } + + return ret; +} + +static DBusMessage* +get_object_property (DBusConnection *connection, + DBusMessage *message, + GObject *object, + GParamSpec *pspec) +{ + GType value_type; + gboolean can_get; + DBusMessage *ret; + GValue value; + DBusMessageIter iter; + + value_type = G_PARAM_SPEC_VALUE_TYPE (pspec); + + ret = dbus_message_new_method_return (message); + if (ret == NULL) + g_error ("out of memory"); + + can_get = TRUE; + g_value_init (&value, value_type); + g_object_get_property (object, pspec->name, &value); + + value_type = G_VALUE_TYPE (&value); + + dbus_message_append_iter_init (message, &iter); + + switch (value_type) + { + case G_TYPE_CHAR: + dbus_message_iter_append_byte (&iter, + g_value_get_char (&value)); + break; + case G_TYPE_UCHAR: + dbus_message_iter_append_byte (&iter, + g_value_get_uchar (&value)); + break; + case G_TYPE_BOOLEAN: + dbus_message_iter_append_boolean (&iter, + g_value_get_boolean (&value)); + break; + case G_TYPE_INT: + dbus_message_iter_append_int32 (&iter, + g_value_get_int (&value)); + break; + case G_TYPE_UINT: + dbus_message_iter_append_uint32 (&iter, + g_value_get_uint (&value)); + break; + /* long gets cut to 32 bits so the remote API is consistent + * on all architectures + */ + case G_TYPE_LONG: + dbus_message_iter_append_int32 (&iter, + g_value_get_long (&value)); + break; + case G_TYPE_ULONG: + dbus_message_iter_append_uint32 (&iter, + g_value_get_ulong (&value)); + break; + case G_TYPE_INT64: + dbus_message_iter_append_int64 (&iter, + g_value_get_int64 (&value)); + break; + case G_TYPE_UINT64: + dbus_message_iter_append_uint64 (&iter, + g_value_get_uint64 (&value)); + break; + case G_TYPE_FLOAT: + dbus_message_iter_append_double (&iter, + g_value_get_float (&value)); + break; + case G_TYPE_DOUBLE: + dbus_message_iter_append_double (&iter, + g_value_get_double (&value)); + break; + case G_TYPE_STRING: + /* FIXME, the GValue string may not be valid UTF-8 */ + dbus_message_iter_append_string (&iter, + g_value_get_string (&value)); + break; + default: + can_get = FALSE; + break; + } + + g_value_unset (&value); + + if (!can_get) + { + dbus_message_unref (ret); + ret = dbus_message_new_error (message, + DBUS_ERROR_UNKNOWN_METHOD, + "Can't convert GType of object property to a D-BUS type"); + } + + return ret; +} + +static DBusHandlerResult +gobject_message_function (DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + const DBusGObjectInfo *info; + GParamSpec *pspec; + GObject *object; + const char *member; + gboolean setter; + gboolean getter; + char *s; + + object = G_OBJECT (user_data); + + if (dbus_message_is_method_call (message, + DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE, + "Introspect")) + return handle_introspect (connection, message, object); + + member = dbus_message_get_member (message); + + /* Try the metainfo, which lets us invoke methods */ + + g_static_mutex_lock (&info_hash_mutex); + /* FIXME this needs to walk up the inheritance tree, not + * just look at the most-derived class + */ + info = g_hash_table_lookup (info_hash, + G_OBJECT_GET_CLASS (object)); + g_static_mutex_unlock (&info_hash_mutex); + + if (info != NULL) + { + + + + } + + /* If no metainfo, we can still do properties and signals + * via standard GLib introspection + */ + setter = (member[0] == 's' && member[1] == 'e' && member[2] == 't'); + getter = (member[0] == 'g' && member[1] == 'e' && member[2] == 't'); + + if (!(setter || getter)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + s = javacaps_to_uscore (&member[3]); + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), + s); + + g_free (s); + + if (pspec != NULL) + { + DBusMessage *ret; + + if (setter) + { + ret = set_object_property (connection, message, + object, pspec); + } + else if (getter) + { + ret = get_object_property (connection, message, + object, pspec); + } + else + { + g_assert_not_reached (); + ret = NULL; + } + + g_assert (ret != NULL); + + dbus_connection_send (connection, ret, NULL); + dbus_message_unref (ret); + return DBUS_HANDLER_RESULT_HANDLED; + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusObjectPathVTable gobject_dbus_vtable = { + gobject_unregister_function, + gobject_message_function, + NULL +}; + +/** @} */ /* end of internals */ + +/** + * @addtogroup DBusGLib + * @{ + */ + +/** + * Install introspection information about the given object class + * sufficient to allow methods on the object to be invoked by name. + * The introspection information is normally generated by + * dbus-glib-tool, then this function is called in the + * class_init() for the object class. + * + * Once introspection information has been installed, instances of the + * object registered with dbus_connection_register_gobject() can have + * their methods invoked remotely. + * + * @param object_class class struct of the object + * @param info introspection data generated by dbus-glib-tool + */ +void +dbus_gobject_class_install_info (GObjectClass *object_class, + const DBusGObjectInfo *info) +{ + g_return_if_fail (G_IS_OBJECT_CLASS (object_class)); + + g_static_mutex_lock (&info_hash_mutex); + + if (info_hash == NULL) + { + info_hash = g_hash_table_new (NULL, NULL); /* direct hash */ + } + + g_hash_table_replace (info_hash, object_class, (void*) info); + + g_static_mutex_unlock (&info_hash_mutex); +} + +static char** +split_path (const char *path) +{ + int len; + char **split; + int n_components; + int i, j, comp; + + len = strlen (path); + + n_components = 0; + i = 0; + while (i < len) + { + if (path[i] == '/') + n_components += 1; + ++i; + } + + split = g_new0 (char*, n_components + 1); + + comp = 0; + i = 0; + while (i < len) + { + if (path[i] == '/') + ++i; + j = i; + + while (j < len && path[j] != '/') + ++j; + + /* Now [i, j) is the path component */ + g_assert (i < j); + g_assert (path[i] != '/'); + g_assert (j == len || path[j] == '/'); + + split[comp] = g_strndup (&path[i], j - i + 1); + + split[comp][j-i] = '\0'; + + ++comp; + i = j; + } + g_assert (i == len); + + return split; +} + +/** + * Registers a GObject at the given path. Properties, methods, and signals + * of the object can then be accessed remotely. Methods are only available + * if method introspection data has been added to the object's class + * with g_object_class_install_info(). + * + * The registration will be cancelled if either the DBusConnection or + * the GObject gets finalized. + * + * @param connection the D-BUS connection + * @param at_path the path where the object will live (the object's name) + * @param object the object + */ +void +dbus_connection_register_gobject (DBusConnection *connection, + const char *at_path, + GObject *object) +{ + char **split; + + g_return_if_fail (connection != NULL); + g_return_if_fail (at_path != NULL); + g_return_if_fail (G_IS_OBJECT (object)); + + split = split_path (at_path); + + if (!dbus_connection_register_object_path (connection, + (const char**) split, + &gobject_dbus_vtable, + object)) + g_error ("Failed to register GObject with DBusConnection"); + + g_strfreev (split); + + /* FIXME set up memory management (so we break the + * registration if object or connection vanishes) + */ +} + +/** @} */ /* end of public API */ + +#ifdef DBUS_BUILD_TESTS + +/** + * @ingroup DBusGLibInternals + * Unit test for GLib GObject integration ("skeletons") + * @returns #TRUE on success. + */ +dbus_bool_t +_dbus_gobject_test (const char *test_data_dir) +{ + static struct { const char *javacaps; const char *uscore; } name_pairs[] = { + { "setFoo", "set_foo" }, + { "foo", "foo" }, + { "getFooBar", "get_foo_bar" }, + { "Hello", "hello" }, + { "frobateUIHandler", "frobate_ui_handler" } + }; + + return TRUE; +} + +#endif /* DBUS_BUILD_TESTS */ diff --git a/glib/dbus-gparser.c b/glib/dbus-gparser.c index 6fea4abc..c2b54d31 100644 --- a/glib/dbus-gparser.c +++ b/glib/dbus-gparser.c @@ -22,11 +22,152 @@ */ #include "dbus-gparser.h" #include "dbus-gidl.h" +#include + +#include +#define _(x) gettext ((x)) +#define N_(x) x + +#define ELEMENT_IS(name) (strcmp (element_name, (name)) == 0) + +typedef struct +{ + const char *name; + const char **retloc; +} LocateAttr; + +static gboolean +locate_attributes (const char *element_name, + const char **attribute_names, + const char **attribute_values, + GError **error, + const char *first_attribute_name, + const char **first_attribute_retloc, + ...) +{ + va_list args; + const char *name; + const char **retloc; + int n_attrs; +#define MAX_ATTRS 24 + LocateAttr attrs[MAX_ATTRS]; + gboolean retval; + int i; + + g_return_val_if_fail (first_attribute_name != NULL, FALSE); + g_return_val_if_fail (first_attribute_retloc != NULL, FALSE); + + retval = TRUE; + + n_attrs = 1; + attrs[0].name = first_attribute_name; + attrs[0].retloc = first_attribute_retloc; + *first_attribute_retloc = NULL; + + va_start (args, first_attribute_retloc); + + name = va_arg (args, const char*); + retloc = va_arg (args, const char**); + + while (name != NULL) + { + g_return_val_if_fail (retloc != NULL, FALSE); + + g_assert (n_attrs < MAX_ATTRS); + + attrs[n_attrs].name = name; + attrs[n_attrs].retloc = retloc; + n_attrs += 1; + *retloc = NULL; + + name = va_arg (args, const char*); + retloc = va_arg (args, const char**); + } + + va_end (args); + + if (!retval) + return retval; + + i = 0; + while (attribute_names[i]) + { + int j; + gboolean found; + + found = FALSE; + j = 0; + while (j < n_attrs) + { + if (strcmp (attrs[j].name, attribute_names[i]) == 0) + { + retloc = attrs[j].retloc; + + if (*retloc != NULL) + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Attribute \"%s\" repeated twice on the same <%s> element"), + attrs[j].name, element_name); + retval = FALSE; + goto out; + } + + *retloc = attribute_values[i]; + found = TRUE; + } + + ++j; + } + + if (!found) + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Attribute \"%s\" is invalid on <%s> element in this context"), + attribute_names[i], element_name); + retval = FALSE; + goto out; + } + + ++i; + } + + out: + return retval; +} + +static gboolean +check_no_attributes (const char *element_name, + const char **attribute_names, + const char **attribute_values, + GError **error) +{ + if (attribute_names[0] != NULL) + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Attribute \"%s\" is invalid on <%s> element in this context"), + attribute_names[0], element_name); + return FALSE; + } + + return TRUE; +} struct Parser { int refcount; + NodeInfo *result; /* Filled in when we pop the last node */ + GSList *node_stack; + InterfaceInfo *interface; + MethodInfo *method; + SignalInfo *signal; + ArgInfo *arg; }; Parser* @@ -53,7 +194,8 @@ parser_unref (Parser *parser) parser->refcount -= 1; if (parser->refcount == 0) { - + if (parser->result) + node_info_unref (parser->result); g_free (parser); } @@ -64,11 +206,12 @@ parser_check_doctype (Parser *parser, const char *doctype, GError **error) { - g_return_val_if_fail (error == NULL || *error == NULL); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); if (strcmp (doctype, "dbus_description") != 0) { g_set_error (error, + G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, "D-BUS description file has the wrong document type %s, use dbus_description", doctype); @@ -78,6 +221,324 @@ parser_check_doctype (Parser *parser, return TRUE; } +static gboolean +parse_node (Parser *parser, + const char *element_name, + const char **attribute_names, + const char **attribute_values, + GError **error) +{ + const char *name; + NodeInfo *node; + + if (parser->interface || + parser->method || + parser->signal || + parser->arg) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Can't put a <%s> element here"), + element_name); + return FALSE; + } + + name = NULL; + if (!locate_attributes (element_name, attribute_names, + attribute_values, error, + "name", &name, + NULL)) + return FALSE; + + /* Only the root node can have no name */ + if (parser->node_stack != NULL && name == NULL) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("\"%s\" attribute required on <%s> element "), + "name", element_name); + return FALSE; + } + + node = node_info_new (name); + parser->node_stack = g_slist_prepend (parser->node_stack, + node); + + return TRUE; +} + +static gboolean +parse_interface (Parser *parser, + const char *element_name, + const char **attribute_names, + const char **attribute_values, + GError **error) +{ + const char *name; + InterfaceInfo *iface; + NodeInfo *top; + + if (parser->interface || + parser->method || + parser->signal || + parser->arg || + (parser->node_stack == NULL)) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Can't put a <%s> element here"), + element_name); + return FALSE; + } + + name = NULL; + if (!locate_attributes (element_name, attribute_names, + attribute_values, error, + "name", &name, + NULL)) + return FALSE; + + if (name == NULL) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("\"%s\" attribute required on <%s> element "), + "name", element_name); + return FALSE; + } + + top = parser->node_stack->data; + + iface = interface_info_new (name); + node_info_add_interface (top, iface); + interface_info_unref (iface); + + parser->interface = iface; + + return TRUE; +} + +static gboolean +parse_method (Parser *parser, + const char *element_name, + const char **attribute_names, + const char **attribute_values, + GError **error) +{ + const char *name; + MethodInfo *method; + NodeInfo *top; + + if (parser->interface == NULL || + parser->node_stack == NULL || + parser->method || + parser->signal || + parser->arg) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Can't put a <%s> element here"), + element_name); + return FALSE; + } + + name = NULL; + if (!locate_attributes (element_name, attribute_names, + attribute_values, error, + "name", &name, + NULL)) + return FALSE; + + if (name == NULL) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("\"%s\" attribute required on <%s> element "), + "name", element_name); + return FALSE; + } + + top = parser->node_stack->data; + + method = method_info_new (name); + interface_info_add_method (parser->interface, method); + method_info_unref (method); + + parser->method = method; + + return TRUE; +} + +static gboolean +parse_signal (Parser *parser, + const char *element_name, + const char **attribute_names, + const char **attribute_values, + GError **error) +{ + const char *name; + SignalInfo *signal; + NodeInfo *top; + + if (parser->interface == NULL || + parser->node_stack == NULL || + parser->signal || + parser->signal || + parser->arg) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Can't put a <%s> element here"), + element_name); + return FALSE; + } + + name = NULL; + if (!locate_attributes (element_name, attribute_names, + attribute_values, error, + "name", &name, + NULL)) + return FALSE; + + if (name == NULL) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("\"%s\" attribute required on <%s> element "), + "name", element_name); + return FALSE; + } + + top = parser->node_stack->data; + + signal = signal_info_new (name); + interface_info_add_signal (parser->interface, signal); + signal_info_unref (signal); + + parser->signal = signal; + + return TRUE; +} + +static int +basic_type_from_string (const char *str) +{ + if (strcmp (str, "string") == 0) + return DBUS_TYPE_STRING; + else if (strcmp (str, "int32") == 0) + return DBUS_TYPE_INT32; + else if (strcmp (str, "uint32") == 0) + return DBUS_TYPE_UINT32; + else if (strcmp (str, "int64") == 0) + return DBUS_TYPE_INT64; + else if (strcmp (str, "uint64") == 0) + return DBUS_TYPE_UINT64; + else if (strcmp (str, "double") == 0) + return DBUS_TYPE_DOUBLE; + else if (strcmp (str, "byte") == 0) + return DBUS_TYPE_BYTE; + else if (strcmp (str, "boolean") == 0) + return DBUS_TYPE_BOOLEAN; + else if (strcmp (str, "byte") == 0) + return DBUS_TYPE_BYTE; + else if (strcmp (str, "object") == 0) + return DBUS_TYPE_OBJECT_PATH; + else + return DBUS_TYPE_INVALID; +} + +static int +type_from_string (const char *str) +{ + return basic_type_from_string (str); +} + +static gboolean +parse_arg (Parser *parser, + const char *element_name, + const char **attribute_names, + const char **attribute_values, + GError **error) +{ + const char *name; + const char *type; + const char *direction; + ArgDirection dir; + int t; + ArgInfo *arg; + + if (!(parser->method || parser->signal) || + parser->node_stack == NULL || + parser->arg) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Can't put a <%s> element here"), + element_name); + return FALSE; + } + + name = NULL; + if (!locate_attributes (element_name, attribute_names, + attribute_values, error, + "name", &name, + "type", &type, + "direction", &direction, + NULL)) + return FALSE; + + /* name can be null for args */ + + if (type == NULL) + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("\"%s\" attribute required on <%s> element "), + "type", element_name); + return FALSE; + } + + if (direction == NULL) + { + /* methods default to in, signal to out */ + if (parser->method) + direction = "in"; + else if (parser->signal) + direction = "out"; + else + g_assert_not_reached (); + } + + if (strcmp (direction, "in") == 0) + dir = ARG_IN; + else if (strcmp (direction, "out") == 0) + dir = ARG_OUT; + else + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("\"%s\" attribute on <%s> has value \"in\" or \"out\""), + "direction", element_name); + return FALSE; + } + + t = type_from_string (type); + + arg = arg_info_new (name, dir, t); + if (parser->method) + method_info_add_arg (parser->method, arg); + else if (parser->signal) + signal_info_add_arg (parser->signal, arg); + else + g_assert_not_reached (); + + arg_info_unref (arg); + + parser->arg = arg; + + return TRUE; +} + gboolean parser_start_element (Parser *parser, const char *element_name, @@ -85,8 +546,46 @@ parser_start_element (Parser *parser, const char **attribute_values, GError **error) { - g_return_val_if_fail (error == NULL || *error == NULL); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + if (ELEMENT_IS ("node")) + { + if (!parse_node (parser, element_name, attribute_names, + attribute_values, error)) + return FALSE; + } + else if (ELEMENT_IS ("interface")) + { + if (!parse_interface (parser, element_name, attribute_names, + attribute_values, error)) + return FALSE; + } + else if (ELEMENT_IS ("method")) + { + if (!parse_method (parser, element_name, attribute_names, + attribute_values, error)) + return FALSE; + } + else if (ELEMENT_IS ("signal")) + { + if (!parse_signal (parser, element_name, attribute_names, + attribute_values, error)) + return FALSE; + } + else if (ELEMENT_IS ("arg")) + { + if (!parse_arg (parser, element_name, attribute_names, + attribute_values, error)) + return FALSE; + } + else + { + g_set_error (error, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Element <%s> not recognized"), + element_name); + } + return TRUE; } @@ -95,8 +594,40 @@ parser_end_element (Parser *parser, const char *element_name, GError **error) { - g_return_val_if_fail (error == NULL || *error == NULL); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (ELEMENT_IS ("interface")) + { + parser->interface = NULL; + } + else if (ELEMENT_IS ("method")) + { + parser->method = NULL; + } + else if (ELEMENT_IS ("signal")) + { + parser->signal = NULL; + } + else if (ELEMENT_IS ("arg")) + { + parser->arg = NULL; + } + else if (ELEMENT_IS ("node")) + { + NodeInfo *top; + g_assert (parser->node_stack != NULL); + top = parser->node_stack->data; + + parser->node_stack = g_slist_remove (parser->node_stack, + top); + + if (parser->node_stack == NULL) + parser->result = top; /* We are done, store the result */ + } + else + g_assert_not_reached (); /* should have had an error on start_element */ + return TRUE; } @@ -106,7 +637,7 @@ parser_content (Parser *parser, int len, GError **error) { - g_return_val_if_fail (error == NULL || *error == NULL); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); return TRUE; } @@ -115,7 +646,13 @@ gboolean parser_finished (Parser *parser, GError **error) { - g_return_val_if_fail (error == NULL || *error == NULL); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); return TRUE; } + +NodeInfo* +parser_get_nodes (Parser *parser) +{ + return parser->result; +} diff --git a/glib/dbus-gparser.h b/glib/dbus-gparser.h index 01339fbf..3e87165b 100644 --- a/glib/dbus-gparser.h +++ b/glib/dbus-gparser.h @@ -25,10 +25,10 @@ #include #include +#include "dbus-gidl.h" G_BEGIN_DECLS - typedef struct Parser Parser; Parser* parser_new (void); @@ -52,7 +52,13 @@ gboolean parser_content (Parser *parser, gboolean parser_finished (Parser *parser, GError **error); +Parser* description_load_from_file (const char *filename, + GError **error); +Parser* description_load_from_string (const char *str, + int len, + GError **error); +NodeInfo* parser_get_nodes (Parser *parser); G_END_DECLS -- cgit From 0453b2be603d4a8fcd12be3097b7eadc25838018 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 3 Sep 2003 23:27:36 +0000 Subject: forgot to cvs add dbus-gtest.[hc] --- glib/dbus-gtest.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ glib/dbus-gtest.h | 34 ++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 glib/dbus-gtest.c create mode 100644 glib/dbus-gtest.h (limited to 'glib') diff --git a/glib/dbus-gtest.c b/glib/dbus-gtest.c new file mode 100644 index 00000000..b853d3ed --- /dev/null +++ b/glib/dbus-gtest.c @@ -0,0 +1,73 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-test.c Program to run all tests + * + * Copyright (C) 2002, 2003 Red Hat Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include "dbus-gtest.h" +#include +#include + +#ifdef DBUS_BUILD_TESTS +static void +die (const char *failure) +{ + fprintf (stderr, "Unit test failed: %s\n", failure); + exit (1); +} +#endif /* DBUS_BUILD_TESTS */ + +/** + * An exported symbol to be run in order to execute + * unit tests. Should not be used by + * any app other than our test app, this symbol + * won't exist in some builds of the library. + * (with --enable-tests=no) + * + * @param test_data_dir the directory with test data (test/data normally) + */ +void +dbus_glib_internal_do_not_use_run_tests (const char *test_data_dir) +{ +#ifdef DBUS_BUILD_TESTS + if (test_data_dir == NULL) + test_data_dir = g_getenv ("DBUS_TEST_DATA"); + + if (test_data_dir != NULL) + printf ("Test data in %s\n", test_data_dir); + else + printf ("No test data!\n"); + + printf ("%s: running mainloop integration tests\n", "dbus-glib-test"); + if (!_dbus_gmain_test (test_data_dir)) + die ("gmain"); + + printf ("%s: running GObject tests\n", "dbus-glib-test"); + if (!_dbus_gobject_test (test_data_dir)) + die ("gobject"); + + printf ("%s: completed successfully\n", "dbus-glib-test"); +#else + printf ("Not compiled with unit tests, not running any\n"); +#endif +} + + diff --git a/glib/dbus-gtest.h b/glib/dbus-gtest.h new file mode 100644 index 00000000..6a33bdae --- /dev/null +++ b/glib/dbus-gtest.h @@ -0,0 +1,34 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-gtest.h Declarations of test functions. + * + * Copyright (C) 2003 Red Hat Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef DBUS_GLIB_TEST_H +#define DBUS_GLIB_TEST_H + +#include "dbus-glib.h" + +dbus_bool_t _dbus_gmain_test (const char *test_data_dir); +dbus_bool_t _dbus_gobject_test (const char *test_data_dir); + +void dbus_glib_internal_do_not_use_run_tests (const char *test_data_dir); + +#endif /* DBUS_GLIB_TEST_H */ -- cgit From 636be6f92d4d8effd392ad1f894738849ec7af76 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Thu, 4 Sep 2003 00:21:36 +0000 Subject: 2003-09-03 Havoc Pennington * test/glib/Makefile.am: add this with random glib-linked test programs * glib/Makefile.am: remove the random test programs from here, leave only the unit tests * glib/dbus-gobject.c (_dbus_gobject_test): add test for uscore/javacaps conversion, and fix (get_object_property, set_object_property): change to .NET convention for mapping props to methods, set_FooBar/get_FooBar, since one language has such a convention we may as well copy it. Plus real methods in either getFooBar or get_foo_bar style won't collide with this convention. --- glib/Makefile.am | 34 +------ glib/dbus-gobject.c | 63 ++++++++++--- glib/test-dbus-glib.c | 52 ----------- glib/test-profile.c | 226 ---------------------------------------------- glib/test-thread-client.c | 98 -------------------- glib/test-thread-server.c | 209 ------------------------------------------ glib/test-thread.h | 1 - 7 files changed, 50 insertions(+), 633 deletions(-) delete mode 100644 glib/test-dbus-glib.c delete mode 100644 glib/test-profile.c delete mode 100644 glib/test-thread-client.c delete mode 100644 glib/test-thread-server.c delete mode 100644 glib/test-thread.h (limited to 'glib') diff --git a/glib/Makefile.am b/glib/Makefile.am index f3b43ed3..65d71cfd 100644 --- a/glib/Makefile.am +++ b/glib/Makefile.am @@ -34,30 +34,9 @@ dbus_glib_tool_LDADD= $(DBUS_GLIB_TOOL_LIBS) libdbus-glib-1.la $(top_builddir)/d if DBUS_BUILD_TESTS -if HAVE_GLIB_THREADS -THREAD_APPS=test-thread-server test-thread-client test-profile - -test_thread_server_SOURCES= \ - test-thread-server.c \ - test-thread.h - -test_thread_server_LDADD= $(DBUS_GLIB_THREADS_LIBS) $(top_builddir)/glib/libdbus-glib-1.la - -test_thread_client_SOURCES= \ - test-thread-client.c \ - test-thread.h - -test_thread_client_LDADD= $(DBUS_GLIB_THREADS_LIBS) $(top_builddir)/glib/libdbus-glib-1.la -endif - ## we use noinst_PROGRAMS not check_PROGRAMS for TESTS so that we ## build even when not doing "make check" -noinst_PROGRAMS= $(TESTS) test-dbus-glib $(THREAD_APPS) - -test_dbus_glib_SOURCES= \ - test-dbus-glib.c - -test_dbus_glib_LDADD= $(top_builddir)/glib/libdbus-glib-1.la +noinst_PROGRAMS= $(TESTS) ## note that TESTS has special meaning (stuff to use in make check) ## so if adding tests not to be run in make check, don't add them to @@ -74,15 +53,4 @@ else ### not building tests TESTS= -if HAVE_GLIB_THREADS -noinst_PROGRAMS=test-profile -endif - endif - -if HAVE_GLIB_THREADS -test_profile_SOURCES= \ - test-profile.c - -test_profile_LDADD= $(DBUS_GLIB_THREADS_LIBS) $(top_builddir)/glib/libdbus-glib-1.la -endif \ No newline at end of file diff --git a/glib/dbus-gobject.c b/glib/dbus-gobject.c index aa53265b..b0f6c139 100644 --- a/glib/dbus-gobject.c +++ b/glib/dbus-gobject.c @@ -35,7 +35,7 @@ static GStaticMutex info_hash_mutex = G_STATIC_MUTEX_INIT; static GHashTable *info_hash = NULL; static char* -javacaps_to_uscore (const char *caps) +wincaps_to_uscore (const char *caps) { const char *p; GString *str; @@ -62,7 +62,7 @@ javacaps_to_uscore (const char *caps) } static char* -uscore_to_javacaps (const char *uscore) +uscore_to_wincaps (const char *uscore) { const char *p; GString *str; @@ -233,11 +233,11 @@ handle_introspect (DBusConnection *connection, can_get = (spec->flags & G_PARAM_READABLE) != 0; - s = uscore_to_javacaps (spec->name); + s = uscore_to_wincaps (spec->name); if (can_set) { - g_string_append (xml, " \n"); @@ -248,7 +248,7 @@ handle_introspect (DBusConnection *connection, if (can_get) { - g_string_append (xml, " \n"); @@ -578,13 +578,13 @@ gobject_message_function (DBusConnection *connection, /* If no metainfo, we can still do properties and signals * via standard GLib introspection */ - setter = (member[0] == 's' && member[1] == 'e' && member[2] == 't'); - getter = (member[0] == 'g' && member[1] == 'e' && member[2] == 't'); + setter = (member[0] == 's' && member[1] == 'e' && member[2] == 't' && member[3] == '_'); + getter = (member[0] == 'g' && member[1] == 'e' && member[2] == 't' && member[3] == '_'); if (!(setter || getter)) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - s = javacaps_to_uscore (&member[3]); + s = wincaps_to_uscore (&member[4]); pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), s); @@ -757,6 +757,7 @@ dbus_connection_register_gobject (DBusConnection *connection, /** @} */ /* end of public API */ #ifdef DBUS_BUILD_TESTS +#include /** * @ingroup DBusGLibInternals @@ -766,14 +767,48 @@ dbus_connection_register_gobject (DBusConnection *connection, dbus_bool_t _dbus_gobject_test (const char *test_data_dir) { - static struct { const char *javacaps; const char *uscore; } name_pairs[] = { - { "setFoo", "set_foo" }, - { "foo", "foo" }, - { "getFooBar", "get_foo_bar" }, - { "Hello", "hello" }, - { "frobateUIHandler", "frobate_ui_handler" } + int i; + static struct { const char *wincaps; const char *uscore; } name_pairs[] = { + { "SetFoo", "set_foo" }, + { "Foo", "foo" }, + { "GetFooBar", "get_foo_bar" }, + { "Hello", "hello" } + + /* Impossible-to-handle cases */ + /* { "FrobateUIHandler", "frobate_ui_handler" } */ }; + i = 0; + while (i < (int) G_N_ELEMENTS (name_pairs)) + { + char *uscore; + char *wincaps; + + uscore = wincaps_to_uscore (name_pairs[i].wincaps); + wincaps = uscore_to_wincaps (name_pairs[i].uscore); + + if (strcmp (uscore, name_pairs[i].uscore) != 0) + { + g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n", + name_pairs[i].wincaps, name_pairs[i].uscore, + uscore); + exit (1); + } + + if (strcmp (wincaps, name_pairs[i].wincaps) != 0) + { + g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n", + name_pairs[i].uscore, name_pairs[i].wincaps, + wincaps); + exit (1); + } + + g_free (uscore); + g_free (wincaps); + + ++i; + } + return TRUE; } diff --git a/glib/test-dbus-glib.c b/glib/test-dbus-glib.c deleted file mode 100644 index beda0a7a..00000000 --- a/glib/test-dbus-glib.c +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ -#include "dbus-glib.h" -#include - -int -main (int argc, char **argv) -{ - DBusConnection *connection; - DBusMessage *message, *reply; - GMainLoop *loop; - DBusError error; - - if (argc < 2) - { - g_printerr ("Give the server address as an argument\n"); - return 1; - } - - loop = g_main_loop_new (NULL, FALSE); - - dbus_error_init (&error); - connection = dbus_connection_open (argv[1], &error); - if (connection == NULL) - { - g_printerr ("Failed to open connection to %s: %s\n", argv[1], - error.message); - dbus_error_free (&error); - return 1; - } - - dbus_connection_setup_with_g_main (connection, NULL); - - message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, - DBUS_PATH_ORG_FREEDESKTOP_DBUS, - DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, - "Hello"); - - dbus_error_init (&error); - reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error); - if (reply == NULL) - { - g_printerr ("Error on hello message: %s\n", error.message); - dbus_error_free (&error); - return 1; - } - - g_print ("reply received\n"); - - g_main_loop_run (loop); - - return 0; -} diff --git a/glib/test-profile.c b/glib/test-profile.c deleted file mode 100644 index 6d9d8e7f..00000000 --- a/glib/test-profile.c +++ /dev/null @@ -1,226 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ -/* test-profile.c Program that does basic message-response for timing - * - * Copyright (C) 2003 Red Hat Inc. - * - * Licensed under the Academic Free License version 1.2 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* FIXME this test is wacky since both client and server keep - * sending each other method calls, but nobody sends - * a DBUS_MESSAGE_TYPE_METHOD_RETURN - */ - -#include -#include -#include "dbus-glib.h" -#include - -#define N_CLIENT_THREADS 1 -#define N_ITERATIONS 1000 -#define PAYLOAD_SIZE 30 -#define ECHO_PATH "/org/freedesktop/EchoTest" -#define ECHO_INTERFACE "org.freedesktop.EchoTest" -#define ECHO_METHOD "EchoProfile" - -static const char *address; -static unsigned char *payload; - -static void -send_echo_message (DBusConnection *connection) -{ - DBusMessage *message; - - message = dbus_message_new_method_call (NULL, ECHO_PATH, - ECHO_INTERFACE, ECHO_METHOD); - dbus_message_append_args (message, - DBUS_TYPE_STRING, "Hello World!", - DBUS_TYPE_INT32, 123456, -#if 1 - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - payload, PAYLOAD_SIZE, -#endif - DBUS_TYPE_INVALID); - - dbus_connection_send (connection, message, NULL); - dbus_message_unref (message); - dbus_connection_flush (connection); -} - -static DBusHandlerResult -client_filter (DBusConnection *connection, - DBusMessage *message, - void *user_data) -{ - int *iterations = user_data; - - if (dbus_message_is_signal (message, - DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, - "Disconnected")) - { - g_printerr ("Client thread disconnected\n"); - exit (1); - } - else if (dbus_message_is_method_call (message, - ECHO_INTERFACE, ECHO_METHOD)) - { - *iterations += 1; - if (*iterations >= N_ITERATIONS) - { - g_print ("Completed %d iterations\n", N_ITERATIONS); - exit (0); - } - send_echo_message (connection); - return DBUS_HANDLER_RESULT_HANDLED; - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static void* -thread_func (void *data) -{ - DBusError error; - GMainContext *context; - GMainLoop *loop; - DBusConnection *connection; - int iterations; - - g_printerr ("Starting client thread\n"); - - dbus_error_init (&error); - connection = dbus_connection_open (address, &error); - if (connection == NULL) - { - g_printerr ("could not open connection: %s\n", error.message); - dbus_error_free (&error); - exit (1); - } - - iterations = 1; - - if (!dbus_connection_add_filter (connection, - client_filter, &iterations, NULL)) - g_error ("no memory"); - - context = g_main_context_new (); - loop = g_main_loop_new (context, FALSE); - - dbus_connection_setup_with_g_main (connection, context); - - g_printerr ("Client thread sending message to prime pingpong\n"); - send_echo_message (connection); - g_printerr ("Client thread sent message\n"); - - g_printerr ("Client thread entering main loop\n"); - g_main_loop_run (loop); - g_printerr ("Client thread exiting main loop\n"); - - g_main_loop_unref (loop); - g_main_context_unref (context); - - return NULL; -} - -static DBusHandlerResult -server_filter (DBusConnection *connection, - DBusMessage *message, - void *user_data) -{ - if (dbus_message_is_signal (message, - DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, - "Disconnected")) - { - g_printerr ("Server thread disconnected\n"); - exit (1); - } - else if (dbus_message_is_method_call (message, - ECHO_INTERFACE, - ECHO_METHOD)) - { - send_echo_message (connection); - return DBUS_HANDLER_RESULT_HANDLED; - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static void -new_connection_callback (DBusServer *server, - DBusConnection *new_connection, - void *user_data) -{ - dbus_connection_ref (new_connection); - dbus_connection_setup_with_g_main (new_connection, NULL); - - if (!dbus_connection_add_filter (new_connection, - server_filter, NULL, NULL)) - g_error ("no memory"); - - - /* FIXME we leak the handler */ -} - -int -main (int argc, char *argv[]) -{ - GMainLoop *loop; - DBusError error; - DBusServer *server; - int i; - - g_thread_init (NULL); - dbus_gthread_init (); - - dbus_error_init (&error); - server = dbus_server_listen ("unix:tmpdir="DBUS_TEST_SOCKET_DIR, - &error); - if (server == NULL) - { - g_printerr ("Could not start server: %s\n", - error.message); - return 1; - } - - address = dbus_server_get_address (server); - payload = g_malloc (PAYLOAD_SIZE); - - dbus_server_set_new_connection_function (server, - new_connection_callback, - NULL, NULL); - - loop = g_main_loop_new (NULL, FALSE); - - dbus_server_setup_with_g_main (server, NULL); - - for (i = 0; i < N_CLIENT_THREADS; i++) - { - g_thread_create (thread_func, NULL, FALSE, NULL); - } - - g_printerr ("Server thread entering main loop\n"); - g_main_loop_run (loop); - g_printerr ("Server thread exiting main loop\n"); - - dbus_server_unref (server); - - g_main_loop_unref (loop); - - return 0; -} - diff --git a/glib/test-thread-client.c b/glib/test-thread-client.c deleted file mode 100644 index d51d4e6a..00000000 --- a/glib/test-thread-client.c +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include "dbus-glib.h" -#include -#include -#include - -#include "test-thread.h" - -DBusConnection *connection; - -static gpointer -thread_func (gpointer data) -{ - gint32 threadnr = GPOINTER_TO_INT (data); - guint32 counter = 0; - DBusMessageIter iter; - DBusMessage *message; - char *str; - - while (1) - { - message = dbus_message_new_method_call (NULL, - "/org/freedesktop/ThreadTest", - "org.freedesktop.ThreadTest", - "TestMethod"); - - dbus_message_append_iter_init (message, &iter); - - if (!dbus_message_iter_append_int32 (&iter, threadnr)) - { - g_print ("thread %d: append threadnr failed\n", threadnr); - } - - if (!dbus_message_iter_append_uint32 (&iter, counter)) - { - g_print ("thread %d: append counter (%d) failed\n", threadnr, counter); - } - - str = g_strdup_printf ("Thread %d-%d\n", threadnr, counter); - if (!dbus_message_iter_append_string (&iter, str)) - { - g_print ("thread %d: append string (%s) failed\n", threadnr, str); - } - g_free (str); - - if (!dbus_connection_send (connection, - message, - NULL)) - { - g_print ("thread %d: send message failed\n", threadnr); - } - - dbus_message_unref (message); - - counter ++; - } - - return NULL; -} - -int -main (int argc, char *argv[]) -{ - GMainLoop *loop; - DBusError error; - int i; - - g_thread_init (NULL); - dbus_gthread_init (); - - if(argc < 2) - { - g_error("Need an address as argv[1]\n"); - return 1; - } - - dbus_error_init (&error); - connection = dbus_connection_open (argv[1], &error); - if (connection == NULL) - { - g_printerr ("could not open connection: %s\n", error.message); - dbus_error_free (&error); - return 1; - } - - dbus_connection_setup_with_g_main (connection, NULL); - - for (i = 0; i < N_TEST_THREADS; i++) - { - g_thread_create (thread_func, GINT_TO_POINTER (i), FALSE, NULL); - } - - loop = g_main_loop_new (NULL, FALSE); - g_main_run (loop); - - return 0; -} - diff --git a/glib/test-thread-server.c b/glib/test-thread-server.c deleted file mode 100644 index 8898ca7f..00000000 --- a/glib/test-thread-server.c +++ /dev/null @@ -1,209 +0,0 @@ -#include -#include "dbus-glib.h" -#include -#include - -#include "test-thread.h" - -typedef struct { - guint32 counters[N_TEST_THREADS]; -} ThreadTestData; - -static ThreadTestData * -thread_test_data_new (void) -{ - ThreadTestData *data; - - data = g_new0 (ThreadTestData, 1); - - return data; -} - -static void -thread_test_data_free (ThreadTestData *data) -{ - g_free (data); -} - -static DBusHandlerResult -filter_test_message (DBusConnection *connection, - DBusMessage *message, - void *user_data) -{ - ThreadTestData *data = user_data; - DBusMessageIter iter; - gint32 threadnr; - guint32 counter; - char *str, *expected_str; - GString *counter_str; - int i; - - if (!dbus_message_is_method_call (message, "org.freedesktop.ThreadTest", - "TestMethod")) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - dbus_message_iter_init (message, &iter); - - if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT32) - { - g_print ("First arg not right type\n"); - goto out; - } - threadnr = dbus_message_iter_get_int32 (&iter); - if (threadnr < 0 || threadnr >= N_TEST_THREADS) - { - g_print ("Invalid thread nr\n"); - goto out; - } - - if (! dbus_message_iter_next (&iter)) - { - g_print ("Couldn't get second arg\n"); - goto out; - } - - if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32) - { - g_print ("Second arg not right type\n"); - goto out; - } - - counter = dbus_message_iter_get_uint32 (&iter); - - if (counter != data->counters[threadnr]) - { - g_print ("Thread %d, counter %d, expected %d\n", threadnr, counter, data->counters[threadnr]); - goto out; - } - data->counters[threadnr]++; - - if (! dbus_message_iter_next (&iter)) - { - g_print ("Couldn't get third arg\n"); - goto out; - } - - if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) - { - g_print ("Third arg not right type\n"); - goto out; - } - - str = dbus_message_iter_get_string (&iter); - - if (str == NULL) - { - g_print ("No third arg\n"); - goto out; - } - - expected_str = g_strdup_printf ("Thread %d-%d\n", threadnr, counter); - if (strcmp (expected_str, str) != 0) - { - g_print ("Wrong string '%s', expected '%s'\n", str, expected_str); - goto out; - } - g_free (str); - g_free (expected_str); - - if (dbus_message_iter_next (&iter)) - { - g_print ("Extra args on end of message\n"); - goto out; - } - - dbus_connection_flush (connection); - - counter_str = g_string_new (""); - for (i = 0; i < N_TEST_THREADS; i++) - { - g_string_append_printf (counter_str, "%d ", data->counters[i]); - } - g_print ("%s\r", counter_str->str); - g_string_free (counter_str, TRUE); - - out: - return DBUS_HANDLER_RESULT_HANDLED; -} - -static DBusHandlerResult -filter_disconnect (DBusConnection *connection, - DBusMessage *message, - void *user_data) -{ - if (!dbus_message_is_signal (message, DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, - "Disconnected")) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - g_print ("connection disconnected\n"); - dbus_connection_unref (connection); - - return DBUS_HANDLER_RESULT_HANDLED; -} - -static void -new_connection_callback (DBusServer *server, - DBusConnection *new_connection, - void *user_data) -{ - ThreadTestData * data; - - g_print ("new_connection_callback\n"); - - dbus_connection_ref (new_connection); - dbus_connection_setup_with_g_main (new_connection, NULL); - - data = thread_test_data_new (); - - if (!dbus_connection_add_filter (new_connection, - filter_test_message, data, - (DBusFreeFunction) thread_test_data_free)) - goto nomem; - - if (!dbus_connection_add_filter (new_connection, - filter_disconnect, NULL, NULL)) - goto nomem; - - return; - - nomem: - g_error ("no memory to setup new connection"); -} - -int -main (int argc, char *argv[]) -{ - GMainLoop *loop; - DBusServer *server; - DBusError error; - - g_thread_init (NULL); - dbus_gthread_init (); - - if (argc < 2) - { - fprintf (stderr, "Give the server address as an argument\n"); - return 1; - } - - dbus_error_init (&error); - server = dbus_server_listen (argv[1], &error); - if (server == NULL) - { - fprintf (stderr, "Failed to start server on %s: %s\n", - argv[1], error.message); - dbus_error_free (&error); - return 1; - } - - dbus_server_set_new_connection_function (server, - new_connection_callback, - NULL, NULL); - - dbus_server_setup_with_g_main (server, NULL); - - loop = g_main_loop_new (NULL, FALSE); - g_main_run (loop); - - return 0; -} diff --git a/glib/test-thread.h b/glib/test-thread.h deleted file mode 100644 index 8c78fba2..00000000 --- a/glib/test-thread.h +++ /dev/null @@ -1 +0,0 @@ -#define N_TEST_THREADS 5 -- cgit From d7f8a9510f0987245a7473151dff7bfdd318d7fd Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Fri, 5 Sep 2003 04:14:15 +0000 Subject: more missing files --- glib/dbus-gtest-main.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ glib/dbus-gtool-test.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 glib/dbus-gtest-main.c create mode 100644 glib/dbus-gtool-test.h (limited to 'glib') diff --git a/glib/dbus-gtest-main.c b/glib/dbus-gtest-main.c new file mode 100644 index 00000000..5cc6cb78 --- /dev/null +++ b/glib/dbus-gtest-main.c @@ -0,0 +1,46 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-gtest-main.c Program to run all libdbus-glib tests + * + * Copyright (C) 2003 Red Hat Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "dbus-gtest.h" +#include +#include +#include + +int +main (int argc, + char **argv) +{ + const char *test_data_dir; + + setlocale(LC_ALL, ""); + + + if (argc > 1) + test_data_dir = argv[1]; + else + test_data_dir = NULL; + + dbus_glib_internal_do_not_use_run_tests (test_data_dir); + + return 0; +} diff --git a/glib/dbus-gtool-test.h b/glib/dbus-gtool-test.h new file mode 100644 index 00000000..74a7649f --- /dev/null +++ b/glib/dbus-gtool-test.h @@ -0,0 +1,31 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-gtool-test.h Declarations of test functions for dbus-glib-tool. + * + * Copyright (C) 2003 Red Hat Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef DBUS_GLIB_TOOL_TEST_H +#define DBUS_GLIB_TOOL_TEST_H + +#include "dbus-glib.h" + +dbus_bool_t _dbus_gtool_test (const char *test_data_dir); + +#endif /* DBUS_GLIB_TEST_H */ -- cgit From 32bd6660e07696ed99bfa60b08700e8eae3e96b1 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Sun, 7 Sep 2003 16:21:12 +0000 Subject: Update --- glib/.cvsignore | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'glib') diff --git a/glib/.cvsignore b/glib/.cvsignore index a6e3d2b5..881b4887 100644 --- a/glib/.cvsignore +++ b/glib/.cvsignore @@ -4,11 +4,9 @@ Makefile Makefile.in *.lo *.la -test-dbus-glib +dbus-glib-test +dbus-glib-tool *.bb *.bbg *.da *.gcov -test-thread-client -test-thread-server -test-profile -- cgit From 85ab0327d82e4945ad16630e583d8cc68df25a90 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 7 Sep 2003 23:04:54 +0000 Subject: 2003-09-07 Havoc Pennington * Make Doxygen contented. --- glib/dbus-gidl.c | 4 ++++ glib/dbus-gidl.h | 4 ++++ glib/dbus-glib.h | 23 ++++++++++++++++------- glib/dbus-gloader-expat.c | 13 ++++++++----- glib/dbus-gmain.c | 3 +++ glib/dbus-gparser.c | 4 ++++ glib/dbus-gproxy.c | 17 +++++++++++------ 7 files changed, 50 insertions(+), 18 deletions(-) (limited to 'glib') diff --git a/glib/dbus-gidl.c b/glib/dbus-gidl.c index 12468abb..b867d178 100644 --- a/glib/dbus-gidl.c +++ b/glib/dbus-gidl.c @@ -24,6 +24,8 @@ #include "dbus-gidl.h" +#ifndef DOXYGEN_SHOULD_SKIP_THIS + struct NodeInfo { int refcount; @@ -402,3 +404,5 @@ _dbus_gidl_test (void) } #endif /* DBUS_BUILD_TESTS */ + +#endif /* DOXYGEN_SHOULD_SKIP_THIS */ diff --git a/glib/dbus-gidl.h b/glib/dbus-gidl.h index 6e4e207a..7a667240 100644 --- a/glib/dbus-gidl.h +++ b/glib/dbus-gidl.h @@ -24,6 +24,8 @@ #ifndef DBUS_GLIB_IDL_H #define DBUS_GLIB_IDL_H +#ifndef DOXYGEN_SHOULD_SKIP_THIS + #include #include @@ -90,3 +92,5 @@ ArgDirection arg_info_get_direction (ArgInfo *info); G_END_DECLS #endif /* DBUS_GLIB_IDL_H */ + +#endif /* DOXYGEN_SHOULD_SKIP_THIS */ diff --git a/glib/dbus-glib.h b/glib/dbus-glib.h index 3a87dec2..4015dd99 100644 --- a/glib/dbus-glib.h +++ b/glib/dbus-glib.h @@ -39,19 +39,28 @@ void dbus_server_setup_with_g_main (DBusServer *server, typedef struct DBusGObjectInfo DBusGObjectInfo; typedef struct DBusGMethodInfo DBusGMethodInfo; +/** + * Object typically generated by dbus-glib-tool that + * stores a mapping from introspection data to a + * function pointer for a C method to be invoked. + */ struct DBusGMethodInfo { - GCallback function; - DBusHandleMessageFunction marshaller; - int data_offset; + GCallback function; /**< C method to invoke */ + DBusHandleMessageFunction marshaller; /**< Marshaller to go DBusMessage to C method */ + int data_offset; /**< Offset into the introspection data */ }; +/** + * Introspection data for a GObject, normally autogenerated by + * a tool such as dbus-glib-tool. + */ struct DBusGObjectInfo { - const DBusGMethodInfo *infos; - const unsigned char *data; - void *dbus_internal_padding1; - void *dbus_internal_padding2; + const DBusGMethodInfo *infos; /**< Array of method pointers */ + const unsigned char *data; /**< Introspection data */ + void *dbus_internal_padding1; /**< Reserved for expansion */ + void *dbus_internal_padding2; /**< Reserved for expansion */ }; void dbus_gobject_class_install_info (GObjectClass *object_class, diff --git a/glib/dbus-gloader-expat.c b/glib/dbus-gloader-expat.c index 050d3532..149e7117 100644 --- a/glib/dbus-gloader-expat.c +++ b/glib/dbus-gloader-expat.c @@ -43,13 +43,16 @@ static XML_Memory_Handling_Suite memsuite = g_free }; +/** + * Context for Expat parser for introspection data. + */ typedef struct { - Parser *parser; - const char *filename; - GString *content; - GError **error; - gboolean failed; + Parser *parser; /**< The parser for the introspection data */ + const char *filename; /**< The filename being loaded */ + GString *content; /**< The content of the current element */ + GError **error; /**< Error return location */ + gboolean failed; /**< True if parse has failed */ } ExpatParseContext; static dbus_bool_t diff --git a/glib/dbus-gmain.c b/glib/dbus-gmain.c index 36c6c6b4..c33f47e8 100644 --- a/glib/dbus-gmain.c +++ b/glib/dbus-gmain.c @@ -49,6 +49,9 @@ */ typedef struct DBusGSource DBusGSource; +/** + * A GSource subclass for a DBusConnection. + */ struct DBusGSource { GSource source; /**< the parent GSource */ diff --git a/glib/dbus-gparser.c b/glib/dbus-gparser.c index c2b54d31..f7264b5e 100644 --- a/glib/dbus-gparser.c +++ b/glib/dbus-gparser.c @@ -28,6 +28,8 @@ #define _(x) gettext ((x)) #define N_(x) x +#ifndef DOXYGEN_SHOULD_SKIP_THIS + #define ELEMENT_IS(name) (strcmp (element_name, (name)) == 0) typedef struct @@ -656,3 +658,5 @@ parser_get_nodes (Parser *parser) { return parser->result; } + +#endif /* DOXYGEN_SHOULD_SKIP_THIS */ diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c index 01a6b4b9..8951707b 100644 --- a/glib/dbus-gproxy.c +++ b/glib/dbus-gproxy.c @@ -28,17 +28,22 @@ * @{ */ +/** + * Internals of DBusGProxy + */ struct DBusGProxy { - GStaticMutex lock; - int refcount; - DBusConnection *connection; - char *service; - char *interface; - char *path; + GStaticMutex lock; /**< Thread lock */ + int refcount; /**< Reference count */ + DBusConnection *connection; /**< Connection to communicate over */ + char *service; /**< Service messages go to or NULL */ + char *interface; /**< Interface messages go to or NULL */ + char *path; /**< Path messages go to or NULL */ }; +/** Lock the DBusGProxy */ #define LOCK_PROXY(proxy) (g_static_mutex_lock (&(proxy)->lock)) +/** Unlock the DBusGProxy */ #define UNLOCK_PROXY(proxy) (g_static_mutex_unlock (&(proxy)->lock)) static DBusGProxy* -- cgit From 583994cb3b7f5562fb7b8c37b4cb0d5af78e4ce2 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 17 Sep 2003 03:52:07 +0000 Subject: 2003-09-15 Havoc Pennington * dbus/dbus-pending-call.c: add the get/set object data boilerplate as for DBusConnection, etc. Use generic object data for the notify callback. * glib/dbus-gparser.c (parse_node): parse child nodes * tools/dbus-viewer.c: more hacking on the dbus-viewer * glib/dbus-gutils.c (_dbus_gutils_split_path): add a file to contain functions shared between the convenience lib and the installed lib * glib/Makefile.am (libdbus_glib_1_la_LDFLAGS): add -export-symbols-regex to the GLib library * dbus/dbus-object-tree.c (_dbus_object_tree_dispatch_and_unlock): fix the locking in here, and add a default handler for Introspect() that just returns sub-nodes. 2003-09-14 Havoc Pennington * glib/dbus-gthread.c (dbus_g_thread_init): rename to make g_foo rather than gfoo consistent * glib/dbus-gproxy.h: delete for now, move contents to dbus-glib.h, because the include files don't work right since we aren't in the dbus/ subdir. * glib/dbus-gproxy.c (dbus_gproxy_send): finish implementing (dbus_gproxy_end_call): finish (dbus_gproxy_begin_call): finish * glib/dbus-gmain.c (dbus_set_g_error): new * glib/dbus-gobject.c (handle_introspect): include information about child nodes in the introspection * dbus/dbus-connection.c (dbus_connection_list_registered): new function to help in implementation of introspection * dbus/dbus-object-tree.c (_dbus_object_tree_list_registered_and_unlock): new function 2003-09-12 Havoc Pennington * glib/dbus-gidl.h: add common base class for all the foo_info types * tools/dbus-viewer.c: add GTK-based introspection UI thingy similar to kdcop * test/Makefile.am: try test srcdir -ef . in addition to test srcdir = ., one of them should work (yeah lame) * glib/Makefile.am: build the "idl" parser stuff as a convenience library * glib/dbus-gparser.h: make description_load routines return NodeInfo* not Parser* * Makefile.am (SUBDIRS): build test dir after all library dirs * configure.in: add GTK+ detection --- glib/Makefile.am | 29 ++++-- glib/dbus-gidl.c | 226 +++++++++++++++++++++++++++++++++++----------- glib/dbus-gidl.h | 26 +++++- glib/dbus-glib.h | 71 +++++++++++++-- glib/dbus-gloader-expat.c | 19 ++-- glib/dbus-gmain.c | 41 +++++++++ glib/dbus-gobject.c | 89 +++++++----------- glib/dbus-gparser.c | 8 ++ glib/dbus-gparser.h | 10 +- glib/dbus-gproxy.c | 101 +++++++++++++++++---- glib/dbus-gtest.c | 4 + glib/dbus-gtest.h | 1 + glib/dbus-gthread.c | 2 +- 13 files changed, 471 insertions(+), 156 deletions(-) (limited to 'glib') diff --git a/glib/Makefile.am b/glib/Makefile.am index 65d71cfd..a45aa593 100644 --- a/glib/Makefile.am +++ b/glib/Makefile.am @@ -5,8 +5,7 @@ dbusincludedir=$(includedir)/dbus-1.0/dbus lib_LTLIBRARIES=libdbus-glib-1.la dbusinclude_HEADERS= \ - dbus-glib.h \ - dbus-gproxy.h + dbus-glib.h libdbus_glib_1_la_SOURCES = \ dbus-gmain.c \ @@ -14,23 +13,36 @@ libdbus_glib_1_la_SOURCES = \ dbus-gproxy.c \ dbus-gtest.c \ dbus-gtest.h \ - dbus-gthread.c + dbus-gthread.c \ + dbus-gutils.c \ + dbus-gutils.h libdbus_glib_1_la_LIBADD= $(DBUS_GLIB_LIBS) $(top_builddir)/dbus/libdbus-1.la +## don't export symbols that start with "_" (we use this +## convention for internal symbols) +libdbus_glib_1_la_LDFLAGS= -export-symbols-regex "^[^_].*" -bin_PROGRAMS=dbus-glib-tool +# convenience lib used here and by dbus-viewer +noinst_LTLIBRARIES=libdbus-gtool.la -dbus_glib_tool_SOURCES = \ +libdbus_gtool_la_SOURCES = \ dbus-gidl.c \ dbus-gidl.h \ - dbus-glib-tool.c \ dbus-gloader-expat.c \ dbus-gparser.c \ dbus-gparser.h \ - dbus-gtool-test.h + dbus-gutils.c \ + dbus-gutils.h +libdbus_gtool_la_LIBADD = libdbus-glib-1.la -dbus_glib_tool_LDADD= $(DBUS_GLIB_TOOL_LIBS) libdbus-glib-1.la $(top_builddir)/dbus/libdbus-1.la +bin_PROGRAMS=dbus-glib-tool + +dbus_glib_tool_SOURCES = \ + dbus-glib-tool.c \ + dbus-gtool-test.h + +dbus_glib_tool_LDADD= $(DBUS_GLIB_TOOL_LIBS) libdbus-gtool.la if DBUS_BUILD_TESTS @@ -54,3 +66,4 @@ else TESTS= endif + diff --git a/glib/dbus-gidl.c b/glib/dbus-gidl.c index b867d178..596b43ca 100644 --- a/glib/dbus-gidl.c +++ b/glib/dbus-gidl.c @@ -26,43 +26,131 @@ #ifndef DOXYGEN_SHOULD_SKIP_THIS -struct NodeInfo +struct BaseInfo { - int refcount; + unsigned int refcount : 28; + unsigned int type : 4; char *name; +}; + +struct NodeInfo +{ + BaseInfo base; GSList *interfaces; + GSList *nodes; }; struct InterfaceInfo { - int refcount; - char *name; + BaseInfo base; + /* Since we have BaseInfo now these could be one list */ GSList *methods; GSList *signals; }; struct MethodInfo { - int refcount; + BaseInfo base; GSList *args; - char *name; }; struct SignalInfo { - int refcount; + BaseInfo base; GSList *args; - char *name; }; struct ArgInfo { - int refcount; - char *name; + BaseInfo base; int type; ArgDirection direction; }; +void +base_info_ref (BaseInfo *info) +{ + g_return_if_fail (info != NULL); + g_return_if_fail (info->refcount > 0); + + info->refcount += 1; +} + +static void +base_info_free (void *ptr) +{ + BaseInfo *info; + + info = ptr; + + g_free (info->name); + g_free (info); +} + +void +base_info_unref (BaseInfo *info) +{ + g_return_if_fail (info != NULL); + g_return_if_fail (info->refcount > 0); + + /* This is sort of bizarre, BaseInfo was tacked on later */ + + switch (info->type) + { + case INFO_TYPE_NODE: + node_info_unref ((NodeInfo*) info); + break; + case INFO_TYPE_INTERFACE: + interface_info_unref ((InterfaceInfo*) info); + break; + case INFO_TYPE_SIGNAL: + signal_info_unref ((SignalInfo*) info); + break; + case INFO_TYPE_METHOD: + method_info_unref ((MethodInfo*) info); + break; + case INFO_TYPE_ARG: + arg_info_unref ((ArgInfo*) info); + break; + } +} + +InfoType +base_info_get_type (BaseInfo *info) +{ + return info->type; +} + +const char* +base_info_get_name (BaseInfo *info) +{ + return info->name; +} + +void +base_info_set_name (BaseInfo *info, + const char *name) +{ + char *old; + + old = info->name; + info->name = g_strdup (name); + g_free (old); +} + +GType +base_info_get_gtype (void) +{ + static GType our_type = 0; + + if (our_type == 0) + our_type = g_boxed_type_register_static ("BaseInfo", + (GBoxedCopyFunc) base_info_ref, + (GBoxedFreeFunc) base_info_unref); + + return our_type; +} + static void free_interface_list (GSList **interfaces_p) { @@ -77,6 +165,20 @@ free_interface_list (GSList **interfaces_p) *interfaces_p = NULL; } +static void +free_node_list (GSList **nodes_p) +{ + GSList *tmp; + tmp = *nodes_p; + while (tmp != NULL) + { + node_info_unref (tmp->data); + tmp = tmp->next; + } + g_slist_free (*nodes_p); + *nodes_p = NULL; +} + static void free_method_list (GSList **methods_p) { @@ -113,34 +215,35 @@ node_info_new (const char *name) /* name can be NULL */ info = g_new0 (NodeInfo, 1); - info->refcount = 1; - info->name = g_strdup (name); - + info->base.refcount = 1; + info->base.name = g_strdup (name); + info->base.type = INFO_TYPE_NODE; + return info; } void node_info_ref (NodeInfo *info) { - info->refcount += 1; + info->base.refcount += 1; } void node_info_unref (NodeInfo *info) { - info->refcount -= 1; - if (info->refcount == 0) + info->base.refcount -= 1; + if (info->base.refcount == 0) { free_interface_list (&info->interfaces); - g_free (info->name); - g_free (info); + free_node_list (&info->nodes); + base_info_free (info); } } const char* node_info_get_name (NodeInfo *info) { - return info->name; + return info->base.name; } GSList* @@ -157,6 +260,19 @@ node_info_add_interface (NodeInfo *info, info->interfaces = g_slist_append (info->interfaces, interface); } +GSList* +node_info_get_nodes (NodeInfo *info) +{ + return info->nodes; +} + +void +node_info_add_node (NodeInfo *info, + NodeInfo *node) +{ + node_info_ref (node); + info->nodes = g_slist_append (info->nodes, node); +} InterfaceInfo* interface_info_new (const char *name) @@ -164,35 +280,35 @@ interface_info_new (const char *name) InterfaceInfo *info; info = g_new0 (InterfaceInfo, 1); - info->refcount = 1; - info->name = g_strdup (name); - + info->base.refcount = 1; + info->base.name = g_strdup (name); + info->base.type = INFO_TYPE_INTERFACE; + return info; } void interface_info_ref (InterfaceInfo *info) { - info->refcount += 1; + info->base.refcount += 1; } void interface_info_unref (InterfaceInfo *info) { - info->refcount -= 1; - if (info->refcount == 0) + info->base.refcount -= 1; + if (info->base.refcount == 0) { free_method_list (&info->methods); free_signal_list (&info->signals); - g_free (info->name); - g_free (info); + base_info_free (info); } } const char* interface_info_get_name (InterfaceInfo *info) { - return info->name; + return info->base.name; } GSList* @@ -243,34 +359,34 @@ method_info_new (const char *name) MethodInfo *info; info = g_new0 (MethodInfo, 1); - info->refcount = 1; - info->name = g_strdup (name); - + info->base.refcount = 1; + info->base.name = g_strdup (name); + info->base.type = INFO_TYPE_METHOD; + return info; } void method_info_ref (MethodInfo *info) { - info->refcount += 1; + info->base.refcount += 1; } void method_info_unref (MethodInfo *info) { - info->refcount -= 1; - if (info->refcount == 0) + info->base.refcount -= 1; + if (info->base.refcount == 0) { free_arg_list (&info->args); - g_free (info->name); - g_free (info); + base_info_free (info); } } const char* method_info_get_name (MethodInfo *info) { - return info->name; + return info->base.name; } GSList* @@ -293,34 +409,34 @@ signal_info_new (const char *name) SignalInfo *info; info = g_new0 (SignalInfo, 1); - info->refcount = 1; - info->name = g_strdup (name); - + info->base.refcount = 1; + info->base.name = g_strdup (name); + info->base.type = INFO_TYPE_SIGNAL; + return info; } void signal_info_ref (SignalInfo *info) { - info->refcount += 1; + info->base.refcount += 1; } void signal_info_unref (SignalInfo *info) { - info->refcount -= 1; - if (info->refcount == 0) + info->base.refcount -= 1; + if (info->base.refcount == 0) { free_arg_list (&info->args); - g_free (info->name); - g_free (info); + base_info_free (info); } } const char* signal_info_get_name (SignalInfo *info) { - return info->name; + return info->base.name; } GSList* @@ -345,10 +461,11 @@ arg_info_new (const char *name, ArgInfo *info; info = g_new0 (ArgInfo, 1); - info->refcount = 1; - + info->base.refcount = 1; + info->base.type = INFO_TYPE_ARG; + /* name can be NULL */ - info->name = g_strdup (name); + info->base.name = g_strdup (name); info->direction = direction; info->type = type; @@ -358,23 +475,22 @@ arg_info_new (const char *name, void arg_info_ref (ArgInfo *info) { - info->refcount += 1; + info->base.refcount += 1; } void arg_info_unref (ArgInfo *info) { - info->refcount -= 1; - if (info->refcount == 0) + info->base.refcount -= 1; + if (info->base.refcount == 0) { - g_free (info->name); - g_free (info); + base_info_free (info); } } const char* arg_info_get_name (ArgInfo *info) { - return info->name; + return info->base.name; } int diff --git a/glib/dbus-gidl.h b/glib/dbus-gidl.h index 7a667240..f95abfbd 100644 --- a/glib/dbus-gidl.h +++ b/glib/dbus-gidl.h @@ -27,10 +27,11 @@ #ifndef DOXYGEN_SHOULD_SKIP_THIS #include -#include +#include G_BEGIN_DECLS +typedef struct BaseInfo BaseInfo; typedef struct NodeInfo NodeInfo; typedef struct InterfaceInfo InterfaceInfo; typedef struct MethodInfo MethodInfo; @@ -43,13 +44,36 @@ typedef enum ARG_OUT } ArgDirection; +typedef enum +{ + INFO_TYPE_NODE, + INFO_TYPE_INTERFACE, + INFO_TYPE_METHOD, + INFO_TYPE_SIGNAL, + INFO_TYPE_ARG + +} InfoType; + +void base_info_ref (BaseInfo *info); +void base_info_unref (BaseInfo *info); +InfoType base_info_get_type (BaseInfo *info); +const char* base_info_get_name (BaseInfo *info); +void base_info_set_name (BaseInfo *info, + const char *name); +GType base_info_get_gtype (void); +#define BASE_INFO_TYPE (base_info_get_gtype ()) + + NodeInfo* node_info_new (const char *name); void node_info_ref (NodeInfo *info); void node_info_unref (NodeInfo *info); const char* node_info_get_name (NodeInfo *info); GSList* node_info_get_interfaces (NodeInfo *info); +GSList* node_info_get_nodes (NodeInfo *info); void node_info_add_interface (NodeInfo *info, InterfaceInfo *interface); +void node_info_add_node (NodeInfo *info, + NodeInfo *child); InterfaceInfo* interface_info_new (const char *name); void interface_info_ref (InterfaceInfo *info); diff --git a/glib/dbus-glib.h b/glib/dbus-glib.h index 4015dd99..63d34485 100644 --- a/glib/dbus-glib.h +++ b/glib/dbus-glib.h @@ -2,6 +2,7 @@ /* dbus-glib.h GLib integration * * Copyright (C) 2002, 2003 CodeFactory AB + * Copyright (C) 2003 Red Hat, Inc. * * Licensed under the Academic Free License version 1.2 * @@ -30,7 +31,22 @@ G_BEGIN_DECLS #define DBUS_INSIDE_DBUS_GLIB_H 1 -void dbus_gthread_init (void); +GQuark dbus_g_error_quark (void); +#define DBUS_GERROR dbus_g_error_quark () + +typedef enum +{ + /* FIXME map all the DBUS_ERROR to DBUS_GERROR, should + * probably be automated in some way, perhaps + * via lame perl script + */ + DBUS_GERROR_FAILED +} DBusGError; + +void dbus_set_g_error (GError **gerror, + DBusError *derror); + +void dbus_g_thread_init (void); void dbus_connection_setup_with_g_main (DBusConnection *connection, GMainContext *context); void dbus_server_setup_with_g_main (DBusServer *server, @@ -63,14 +79,57 @@ struct DBusGObjectInfo void *dbus_internal_padding2; /**< Reserved for expansion */ }; -void dbus_gobject_class_install_info (GObjectClass *object_class, - const DBusGObjectInfo *info); -void dbus_connection_register_gobject (DBusConnection *connection, - const char *at_path, - GObject *object); +void dbus_g_object_class_install_info (GObjectClass *object_class, + const DBusGObjectInfo *info); +void dbus_connection_register_g_object (DBusConnection *connection, + const char *at_path, + GObject *object); + + +typedef struct DBusGProxy DBusGProxy; + +DBusGProxy* dbus_gproxy_new_for_service (DBusConnection *connection, + const char *service_name, + const char *interface_name); +DBusGProxy* dbus_gproxy_new_for_service_owner (DBusConnection *connection, + const char *service_name, + const char *interface_name, + GError **error); +DBusGProxy* dbus_gproxy_new_for_object_path (DBusConnection *connection, + const char *path, + const char *interface_name); +DBusGProxy* dbus_gproxy_new_for_interface (DBusConnection *connection, + const char *interface_name); +void dbus_gproxy_ref (DBusGProxy *proxy); +void dbus_gproxy_unref (DBusGProxy *proxy); +gboolean dbus_gproxy_connect_signal (DBusGProxy *proxy, + const char *signal_name, + GCallback callback, + void *data, + GFreeFunc free_data_func, + GError **error); +DBusPendingCall* dbus_gproxy_begin_call (DBusGProxy *proxy, + const char *method, + int first_arg_type, + ...); +gboolean dbus_gproxy_end_call (DBusGProxy *proxy, + DBusPendingCall *pending, + GError **error, + int first_arg_type, + ...); +void dbus_gproxy_oneway_call (DBusGProxy *proxy, + const char *method, + int first_arg_type, + ...); +void dbus_gproxy_send (DBusGProxy *proxy, + DBusMessage *message, + dbus_uint32_t *client_serial); #undef DBUS_INSIDE_DBUS_GLIB_H G_END_DECLS #endif /* DBUS_GLIB_H */ + + + diff --git a/glib/dbus-gloader-expat.c b/glib/dbus-gloader-expat.c index 149e7117..01587d21 100644 --- a/glib/dbus-gloader-expat.c +++ b/glib/dbus-gloader-expat.c @@ -163,31 +163,32 @@ expat_CharacterDataHandler (void *userData, s, len); } -Parser* +NodeInfo* description_load_from_file (const char *filename, GError **error) { char *contents; gsize len; - Parser *parser; + NodeInfo *nodes; contents = NULL; if (!g_file_get_contents (filename, &contents, &len, error)) return NULL; - parser = description_load_from_string (contents, len, error); + nodes = description_load_from_string (contents, len, error); g_free (contents); - return parser; + return nodes; } -Parser* +NodeInfo* description_load_from_string (const char *str, int len, GError **error) { XML_Parser expat; ExpatParseContext context; + NodeInfo *nodes; g_return_val_if_fail (error == NULL || *error == NULL, NULL); @@ -242,8 +243,11 @@ description_load_from_string (const char *str, XML_ParserFree (expat); g_string_free (context.content, TRUE); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - return context.parser; + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + nodes = parser_get_nodes (context.parser); + node_info_ref (nodes); + parser_unref (context.parser); + return nodes; failed: g_return_val_if_fail (error == NULL || *error != NULL, NULL); @@ -255,3 +259,4 @@ description_load_from_string (const char *str, parser_unref (context.parser); return NULL; } + diff --git a/glib/dbus-gmain.c b/glib/dbus-gmain.c index c33f47e8..2e5604dc 100644 --- a/glib/dbus-gmain.c +++ b/glib/dbus-gmain.c @@ -25,6 +25,10 @@ #include "dbus-glib.h" #include "dbus-gtest.h" +#include +#define _(x) dgettext (GETTEXT_PACKAGE, x) +#define N_(x) x + /** * @defgroup DBusGLib GLib bindings * @ingroup DBus @@ -494,6 +498,43 @@ dbus_server_setup_with_g_main (DBusServer *server, g_error ("Not enough memory to set up DBusServer for use with GLib"); } +/** + * The implementation of DBUS_GERROR error domain. See documentation + * for GError in GLib reference manual. + * + * @returns the error domain quark for use with GError + */ +GQuark +dbus_g_error_quark (void) +{ + static GQuark quark = 0; + if (quark == 0) + quark = g_quark_from_static_string ("g-exec-error-quark"); + return quark; +} + + +/** + * Set a GError return location from a DBusError. + * + * @todo expand the DBUS_GERROR enum and take advantage of it here + * + * @param gerror location to store a GError, or #NULL + * @param derror the DBusError + */ +void +dbus_set_g_error (GError **gerror, + DBusError *derror) +{ + g_return_if_fail (derror != NULL); + g_return_if_fail (dbus_error_is_set (derror)); + + g_set_error (gerror, DBUS_GERROR, + DBUS_GERROR_FAILED, + _("D-BUS error %s: %s"), + derror->name, derror->message); +} + /** @} */ /* end of public API */ #ifdef DBUS_BUILD_TESTS diff --git a/glib/dbus-gobject.c b/glib/dbus-gobject.c index b0f6c139..6e65770f 100644 --- a/glib/dbus-gobject.c +++ b/glib/dbus-gobject.c @@ -24,6 +24,7 @@ #include #include "dbus-glib.h" #include "dbus-gtest.h" +#include "dbus-gutils.h" #include /** @@ -102,6 +103,7 @@ gobject_unregister_function (DBusConnection *connection, object = G_OBJECT (user_data); + /* FIXME */ } @@ -187,6 +189,15 @@ handle_introspect (DBusConnection *connection, unsigned int i; GType last_type; DBusMessage *ret; + char **path; + char **children; + + if (!dbus_message_get_path_decomposed (message, &path)) + g_error ("Out of memory"); + + if (!dbus_connection_list_registered (connection, (const char**) path, + &children)) + g_error ("Out of memory"); xml = g_string_new (NULL); @@ -268,13 +279,23 @@ handle_introspect (DBusConnection *connection, g_free (specs); + /* Append child nodes */ + + i = 0; + while (children[i]) + { + g_string_append_printf (xml, " \n", + children[i]); + ++i; + } + /* Close the XML, and send it to the requesting app */ g_string_append (xml, "\n"); ret = dbus_message_new_method_return (message); if (ret == NULL) - g_error ("out of memory"); + g_error ("Out of memory"); dbus_message_append_args (message, DBUS_TYPE_STRING, xml->str, @@ -285,6 +306,9 @@ handle_introspect (DBusConnection *connection, g_string_free (xml, TRUE); + dbus_free_string_array (path); + dbus_free_string_array (children); + return DBUS_HANDLER_RESULT_HANDLED; } @@ -642,15 +666,15 @@ static DBusObjectPathVTable gobject_dbus_vtable = { * class_init() for the object class. * * Once introspection information has been installed, instances of the - * object registered with dbus_connection_register_gobject() can have + * object registered with dbus_connection_register_g_object() can have * their methods invoked remotely. * * @param object_class class struct of the object * @param info introspection data generated by dbus-glib-tool */ void -dbus_gobject_class_install_info (GObjectClass *object_class, - const DBusGObjectInfo *info) +dbus_g_object_class_install_info (GObjectClass *object_class, + const DBusGObjectInfo *info) { g_return_if_fail (G_IS_OBJECT_CLASS (object_class)); @@ -666,55 +690,6 @@ dbus_gobject_class_install_info (GObjectClass *object_class, g_static_mutex_unlock (&info_hash_mutex); } -static char** -split_path (const char *path) -{ - int len; - char **split; - int n_components; - int i, j, comp; - - len = strlen (path); - - n_components = 0; - i = 0; - while (i < len) - { - if (path[i] == '/') - n_components += 1; - ++i; - } - - split = g_new0 (char*, n_components + 1); - - comp = 0; - i = 0; - while (i < len) - { - if (path[i] == '/') - ++i; - j = i; - - while (j < len && path[j] != '/') - ++j; - - /* Now [i, j) is the path component */ - g_assert (i < j); - g_assert (path[i] != '/'); - g_assert (j == len || path[j] == '/'); - - split[comp] = g_strndup (&path[i], j - i + 1); - - split[comp][j-i] = '\0'; - - ++comp; - i = j; - } - g_assert (i == len); - - return split; -} - /** * Registers a GObject at the given path. Properties, methods, and signals * of the object can then be accessed remotely. Methods are only available @@ -729,9 +704,9 @@ split_path (const char *path) * @param object the object */ void -dbus_connection_register_gobject (DBusConnection *connection, - const char *at_path, - GObject *object) +dbus_connection_register_g_object (DBusConnection *connection, + const char *at_path, + GObject *object) { char **split; @@ -739,7 +714,7 @@ dbus_connection_register_gobject (DBusConnection *connection, g_return_if_fail (at_path != NULL); g_return_if_fail (G_IS_OBJECT (object)); - split = split_path (at_path); + split = _dbus_gutils_split_path (at_path); if (!dbus_connection_register_object_path (connection, (const char**) split, diff --git a/glib/dbus-gparser.c b/glib/dbus-gparser.c index f7264b5e..16d17f3d 100644 --- a/glib/dbus-gparser.c +++ b/glib/dbus-gparser.c @@ -262,7 +262,15 @@ parse_node (Parser *parser, return FALSE; } + node = node_info_new (name); + + if (parser->node_stack != NULL) + { + node_info_add_node (parser->node_stack->data, + node); + } + parser->node_stack = g_slist_prepend (parser->node_stack, node); diff --git a/glib/dbus-gparser.h b/glib/dbus-gparser.h index 3e87165b..cc58e5e0 100644 --- a/glib/dbus-gparser.h +++ b/glib/dbus-gparser.h @@ -52,11 +52,11 @@ gboolean parser_content (Parser *parser, gboolean parser_finished (Parser *parser, GError **error); -Parser* description_load_from_file (const char *filename, - GError **error); -Parser* description_load_from_string (const char *str, - int len, - GError **error); +NodeInfo* description_load_from_file (const char *filename, + GError **error); +NodeInfo* description_load_from_string (const char *str, + int len, + GError **error); NodeInfo* parser_get_nodes (Parser *parser); diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c index 8951707b..59d86a31 100644 --- a/glib/dbus-gproxy.c +++ b/glib/dbus-gproxy.c @@ -20,7 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ -#include "dbus-gproxy.h" +#include "dbus-glib.h" /** * @addtogroup DBusGLibInternals @@ -165,23 +165,59 @@ dbus_gproxy_unref (DBusGProxy *proxy) * To collect the results of the call (which may be an error, * or a reply), use dbus_gproxy_end_call(). * + * @todo this particular function shouldn't die on out of memory, + * since you should be able to do a call with large arguments. + * * @param proxy a proxy for a remote interface * @param method the name of the method to invoke * @param first_arg_type type of the first argument * * @returns opaque pending call object - * - */ + * */ DBusPendingCall* dbus_gproxy_begin_call (DBusGProxy *proxy, const char *method, int first_arg_type, ...) { + DBusPendingCall *pending; + DBusMessage *message; + va_list args; + g_return_val_if_fail (proxy != NULL, NULL); LOCK_PROXY (proxy); + message = dbus_message_new_method_call (proxy->service, + proxy->interface, + proxy->path, + method); + if (message == NULL) + goto oom; + + va_start (args, first_arg_type); + if (!dbus_message_append_args_valist (message, first_arg_type, + args)) + goto oom; + va_end (args); + + if (!dbus_connection_send_with_reply (proxy->connection, + message, + &pending, + -1)) + goto oom; + UNLOCK_PROXY (proxy); + + return pending; + + oom: + /* FIXME we should create a pending call that's + * immediately completed with an error status without + * ever going on the wire. + */ + + g_error ("Out of memory"); + return NULL; } /** @@ -189,7 +225,9 @@ dbus_gproxy_begin_call (DBusGProxy *proxy, * initiated with dbus_gproxy_end_call(). This function will block if * the results haven't yet been received; use * dbus_pending_call_set_notify() to be notified asynchronously that a - * pending call has been completed. + * pending call has been completed. Use + * dbus_pending_call_get_completed() to check whether a call has been + * completed. If it's completed, it will not block. * * If the call results in an error, the error is set as normal for * GError and the function returns #FALSE. @@ -198,12 +236,15 @@ dbus_gproxy_begin_call (DBusGProxy *proxy, * method are stored in the provided varargs list. * The list should be terminated with DBUS_TYPE_INVALID. * + * This function doesn't affect the reference count of the + * #DBusPendingCall, the caller of dbus_gproxy_begin_call() still owns + * a reference. + * * @param proxy a proxy for a remote interface * @param pending the pending call from dbus_gproxy_begin_call() * @param error return location for an error * @param first_arg_type type of first "out" argument - * @returns #FALSE if an error is set - */ + * @returns #FALSE if an error is set */ gboolean dbus_gproxy_end_call (DBusGProxy *proxy, DBusPendingCall *pending, @@ -211,10 +252,37 @@ dbus_gproxy_end_call (DBusGProxy *proxy, int first_arg_type, ...) { + DBusMessage *message; + va_list args; + DBusError derror; + g_return_val_if_fail (proxy != NULL, FALSE); + g_return_val_if_fail (pending != NULL, FALSE); + LOCK_PROXY (proxy); + dbus_pending_call_block (pending); + message = dbus_pending_call_get_reply (pending); + + g_assert (message != NULL); + + dbus_error_init (&derror); + va_start (args, first_arg_type); + if (!dbus_message_get_args_valist (message, &derror, first_arg_type, args)) + { + va_end (args); + goto error; + } + va_end (args); + UNLOCK_PROXY (proxy); + + return TRUE; + + error: + dbus_set_g_error (error, &derror); + dbus_error_free (&derror); + return FALSE; } /** @@ -224,18 +292,17 @@ dbus_gproxy_end_call (DBusGProxy *proxy, * dbus_connection_flush(). * * The message is modified to be addressed to the target interface. - * That is, a destination service field or whatever is needed - * will be added to the message. + * That is, a destination service field or whatever is needed will be + * added to the message. The basic point of this function is to add + * the necessary header fields, otherwise it's equivalent to + * dbus_connection_send(). * * This function adds a reference to the message, so the caller * still owns its original reference. - * - * @todo fix for sending to interfaces and object IDs * * @param proxy a proxy for a remote interface * @param message the message to address and send - * @param client_serial return location for message's serial, or #NULL - */ + * @param client_serial return location for message's serial, or #NULL */ void dbus_gproxy_send (DBusGProxy *proxy, DBusMessage *message, @@ -247,17 +314,19 @@ dbus_gproxy_send (DBusGProxy *proxy, if (proxy->service) { if (!dbus_message_set_destination (message, proxy->service)) - g_error ("Out of memory\n"); + g_error ("Out of memory"); } if (proxy->interface) { - /* FIXME */ + if (!dbus_message_set_interface (message, proxy->interface)) + g_error ("Out of memory"); } if (proxy->path) { - /* FIXME */ + if (!dbus_message_set_path (message, proxy->path)) + g_error ("Out of memory"); } - + if (!dbus_connection_send (proxy->connection, message, client_serial)) g_error ("Out of memory\n"); diff --git a/glib/dbus-gtest.c b/glib/dbus-gtest.c index b853d3ed..48cd13f0 100644 --- a/glib/dbus-gtest.c +++ b/glib/dbus-gtest.c @@ -56,6 +56,10 @@ dbus_glib_internal_do_not_use_run_tests (const char *test_data_dir) else printf ("No test data!\n"); + printf ("%s: running utils tests\n", "dbus-glib-test"); + if (!_dbus_gutils_test (test_data_dir)) + die ("gutils"); + printf ("%s: running mainloop integration tests\n", "dbus-glib-test"); if (!_dbus_gmain_test (test_data_dir)) die ("gmain"); diff --git a/glib/dbus-gtest.h b/glib/dbus-gtest.h index 6a33bdae..1174eb0a 100644 --- a/glib/dbus-gtest.h +++ b/glib/dbus-gtest.h @@ -28,6 +28,7 @@ dbus_bool_t _dbus_gmain_test (const char *test_data_dir); dbus_bool_t _dbus_gobject_test (const char *test_data_dir); +dbus_bool_t _dbus_gutils_test (const char *test_data_dir); void dbus_glib_internal_do_not_use_run_tests (const char *test_data_dir); diff --git a/glib/dbus-gthread.c b/glib/dbus-gthread.c index 71a3c1f5..eb3e5572 100644 --- a/glib/dbus-gthread.c +++ b/glib/dbus-gthread.c @@ -165,7 +165,7 @@ dbus_gcondvar_wake_all (DBusCondVar *cond) * other function in the D-BUS API. */ void -dbus_gthread_init (void) +dbus_g_thread_init (void) { if (!g_thread_supported ()) g_error ("g_thread_init() must be called before dbus_threads_init()"); -- cgit From fafc38bb45db8031fc6f252e86df86dc585fefc9 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 17 Sep 2003 13:56:29 +0000 Subject: must cvs add... --- glib/dbus-gutils.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ glib/dbus-gutils.h | 40 +++++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 glib/dbus-gutils.c create mode 100644 glib/dbus-gutils.h (limited to 'glib') diff --git a/glib/dbus-gutils.c b/glib/dbus-gutils.c new file mode 100644 index 00000000..e99286f8 --- /dev/null +++ b/glib/dbus-gutils.c @@ -0,0 +1,96 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-gutils.c Utils shared between convenience lib and installed lib + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include "dbus-gutils.h" +#include "dbus-gtest.h" +#include + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +char** +_dbus_gutils_split_path (const char *path) +{ + int len; + char **split; + int n_components; + int i, j, comp; + + len = strlen (path); + + n_components = 0; + i = 0; + while (i < len) + { + if (path[i] == '/') + n_components += 1; + ++i; + } + + split = g_new0 (char*, n_components + 1); + + comp = 0; + i = 0; + while (i < len) + { + if (path[i] == '/') + ++i; + j = i; + + while (j < len && path[j] != '/') + ++j; + + /* Now [i, j) is the path component */ + g_assert (i < j); + g_assert (path[i] != '/'); + g_assert (j == len || path[j] == '/'); + + split[comp] = g_strndup (&path[i], j - i + 1); + + split[comp][j-i] = '\0'; + + ++comp; + i = j; + } + g_assert (i == len); + + return split; +} + +#ifdef DBUS_BUILD_TESTS + +/** + * @ingroup DBusGLibInternals + * Unit test for GLib utils internals + * @returns #TRUE on success. + */ +dbus_bool_t +_dbus_gutils_test (const char *test_data_dir) +{ + + return TRUE; +} + +#endif /* DBUS_BUILD_TESTS */ + +#endif /* DOXYGEN_SHOULD_SKIP_THIS */ diff --git a/glib/dbus-gutils.h b/glib/dbus-gutils.h new file mode 100644 index 00000000..af7cee45 --- /dev/null +++ b/glib/dbus-gutils.h @@ -0,0 +1,40 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-gutils.h Utils shared between convenience lib and installed lib + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef DBUS_GLIB_UTILS_H +#define DBUS_GLIB_UTILS_H + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +#include +#include + +G_BEGIN_DECLS + +char** _dbus_gutils_split_path (const char *path); + +G_END_DECLS + +#endif /* DBUS_GLIB_UTILS_H */ + +#endif /* DOXYGEN_SHOULD_SKIP_THIS */ -- cgit From a683a80c409cc4f2e57ba6a3e60d52f91b8657d0 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 21 Sep 2003 19:53:56 +0000 Subject: 2003-09-21 Havoc Pennington Get matching rules mostly working in the bus; only actually parsing the rule text remains. However, the client side of "signal connections" hasn't been started, this patch is only the bus side. * dbus/dispatch.c: fix for the matching rules changes * bus/driver.c (bus_driver_handle_remove_match) (bus_driver_handle_add_match): send an ack reply from these method calls * glib/dbus-gproxy.c (dbus_gproxy_begin_call): fix order of arguments, reported by Seth Nickell * bus/config-parser.c (append_rule_from_element): support eavesdrop=true|false attribute on policies so match rules can be prevented from snooping on the system bus. * bus/dbus-daemon-1.1.in: consistently use terminology "sender" and "destination" in attribute names; fix some docs bugs; add eavesdrop=true|false attribute * bus/driver.c (bus_driver_handle_add_match) (bus_driver_handle_remove_match): handle AddMatch, RemoveMatch messages * dbus/dbus-protocol.h (DBUS_SERVICE_ORG_FREEDESKTOP_BROADCAST): get rid of broadcast service concept, signals are just always broadcast * bus/signals.c, bus/dispatch.c, bus/connection.c, bus/bus.c: mostly implement matching rules stuff (currently only exposed as signal connections) --- glib/dbus-gproxy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'glib') diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c index 59d86a31..b77e7d30 100644 --- a/glib/dbus-gproxy.c +++ b/glib/dbus-gproxy.c @@ -188,8 +188,8 @@ dbus_gproxy_begin_call (DBusGProxy *proxy, LOCK_PROXY (proxy); message = dbus_message_new_method_call (proxy->service, - proxy->interface, proxy->path, + proxy->interface, method); if (message == NULL) goto oom; -- cgit From c9332907b035b52103c5569119d0a7c9fbcb76ac Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Mon, 22 Sep 2003 03:11:12 +0000 Subject: 2003-09-21 Havoc Pennington * glib/dbus-gproxy.c (dbus_gproxy_manager_new): start implementing the proxy manager, didn't get very far. * dbus/dbus-bus.c (dbus_bus_add_match): new (dbus_bus_remove_match): new * glib/dbus-gproxy.c (dbus_gproxy_new_for_service): add a path_name argument; adjust the other not-yet-implemented gproxy constructors to be what I think they should be. --- glib/dbus-glib.h | 25 ++++++++------- glib/dbus-gproxy.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++---- glib/dbus-gproxy.h | 78 -------------------------------------------- 3 files changed, 101 insertions(+), 96 deletions(-) delete mode 100644 glib/dbus-gproxy.h (limited to 'glib') diff --git a/glib/dbus-glib.h b/glib/dbus-glib.h index 63d34485..7fd88e71 100644 --- a/glib/dbus-glib.h +++ b/glib/dbus-glib.h @@ -88,18 +88,19 @@ void dbus_connection_register_g_object (DBusConnection *connection, typedef struct DBusGProxy DBusGProxy; -DBusGProxy* dbus_gproxy_new_for_service (DBusConnection *connection, - const char *service_name, - const char *interface_name); -DBusGProxy* dbus_gproxy_new_for_service_owner (DBusConnection *connection, - const char *service_name, - const char *interface_name, - GError **error); -DBusGProxy* dbus_gproxy_new_for_object_path (DBusConnection *connection, - const char *path, - const char *interface_name); -DBusGProxy* dbus_gproxy_new_for_interface (DBusConnection *connection, - const char *interface_name); +DBusGProxy* dbus_gproxy_new_for_service (DBusConnection *connection, + const char *service_name, + const char *path_name, + const char *interface_name); +DBusGProxy* dbus_gproxy_new_for_service_owner (DBusConnection *connection, + const char *service_name, + const char *path_name, + const char *interface_name, + GError **error); +DBusGProxy* dbus_gproxy_new_for_peer (DBusConnection *connection, + const char *path_name, + const char *interface_name); + void dbus_gproxy_ref (DBusGProxy *proxy); void dbus_gproxy_unref (DBusGProxy *proxy); gboolean dbus_gproxy_connect_signal (DBusGProxy *proxy, diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c index b77e7d30..96a27888 100644 --- a/glib/dbus-gproxy.c +++ b/glib/dbus-gproxy.c @@ -28,6 +28,83 @@ * @{ */ +/** + * DBusGProxyManager's primary task is to route signals to the proxies + * those signals are emitted on. In order to do this it also has to + * track the owners of the services proxies are bound to. + */ +typedef struct +{ + GStaticMutex lock; /**< Thread lock */ + int refcount; /**< Reference count */ + + + +} DBusGProxyManager; + + +/** Lock the DBusGProxyManager */ +#define LOCK_MANAGER(mgr) (g_static_mutex_lock (&(mgr)->lock)) +/** Unlock the DBusGProxyManager */ +#define UNLOCK_MANAGER(mgr) (g_static_mutex_unlock (&(mgr)->lock)) + +static DBusGProxyManager* +dbus_gproxy_manager_new (void) +{ + DBusGProxyManager *manager; + + manager = g_new0 (DBusGProxyManager, 1); + + manager->refcount = 1; + + g_static_mutex_init (&manager->lock); + + return manager; +} + +static void +dbus_gproxy_manager_ref (DBusGProxyManager *manager) +{ + g_assert (manager != NULL); + g_assert (manager->refcount > 0); + + LOCK_MANAGER (manager); + + manager->refcount += 1; + + UNLOCK_MANAGER (manager); +} + +static void +dbus_gproxy_manager_unref (DBusGProxyManager *manager) +{ + g_assert (manager != NULL); + g_assert (manager->refcount > 0); + + LOCK_MANAGER (manager); + manager->refcount -= 1; + if (manager->refcount == 0) + { + UNLOCK_MANAGER (manager); + + g_static_mutex_free (&manager->lock); + + g_free (manager); + } + else + { + UNLOCK_MANAGER (manager); + } +} + +static DBusGProxyManager* +dbus_gproxy_manager_get_for_connection (DBusConnection *connection) +{ + /* FIXME */ + + return NULL; +} + /** * Internals of DBusGProxy */ @@ -37,8 +114,8 @@ struct DBusGProxy int refcount; /**< Reference count */ DBusConnection *connection; /**< Connection to communicate over */ char *service; /**< Service messages go to or NULL */ - char *interface; /**< Interface messages go to or NULL */ char *path; /**< Path messages go to or NULL */ + char *interface; /**< Interface messages go to or NULL */ }; /** Lock the DBusGProxy */ @@ -82,23 +159,27 @@ _dbus_gproxy_new (DBusConnection *connection) * * @param connection the connection to the remote bus or app * @param service_name name of the service on the message bus + * @param path_name name of the object inside the service to call methods on * @param interface_name name of the interface to call methods on * @returns new proxy object */ DBusGProxy* dbus_gproxy_new_for_service (DBusConnection *connection, const char *service_name, + const char *path_name, const char *interface_name) { DBusGProxy *proxy; g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (service_name != NULL, NULL); + g_return_val_if_fail (path_name != NULL, NULL); g_return_val_if_fail (interface_name != NULL, NULL); proxy = _dbus_gproxy_new (connection); proxy->service = g_strdup (service_name); + proxy->path = g_strdup (path_name); proxy->interface = g_strdup (interface_name); return proxy; @@ -144,8 +225,9 @@ dbus_gproxy_unref (DBusGProxy *proxy) UNLOCK_PROXY (proxy); dbus_connection_unref (proxy->connection); - g_free (proxy->interface); g_free (proxy->service); + g_free (proxy->path); + g_free (proxy->interface); g_static_mutex_free (&proxy->lock); g_free (proxy); } @@ -316,14 +398,14 @@ dbus_gproxy_send (DBusGProxy *proxy, if (!dbus_message_set_destination (message, proxy->service)) g_error ("Out of memory"); } - if (proxy->interface) + if (proxy->path) { - if (!dbus_message_set_interface (message, proxy->interface)) + if (!dbus_message_set_path (message, proxy->path)) g_error ("Out of memory"); } - if (proxy->path) + if (proxy->interface) { - if (!dbus_message_set_path (message, proxy->path)) + if (!dbus_message_set_interface (message, proxy->interface)) g_error ("Out of memory"); } diff --git a/glib/dbus-gproxy.h b/glib/dbus-gproxy.h deleted file mode 100644 index 4e8f3f60..00000000 --- a/glib/dbus-gproxy.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ -/* dbus-gproxy.h convenience routines for calling methods, etc. - * - * Copyright (C) 2003 Red Hat, Inc. - * - * Licensed under the Academic Free License version 1.2 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef DBUS_GPROXY_H -#define DBUS_GPROXY_H - -#if !defined (DBUS_INSIDE_DBUS_GLIB_H) && !defined (DBUS_COMPILATION) -#error "Only can be included directly, this file may disappear or change contents." -#endif - -#include -#include -#include /* for GCallback at the moment, we don't link to it */ - -G_BEGIN_DECLS - -typedef struct DBusGProxy DBusGProxy; - -DBusGProxy* dbus_gproxy_new_for_service (DBusConnection *connection, - const char *service_name, - const char *interface_name); -DBusGProxy* dbus_gproxy_new_for_service_owner (DBusConnection *connection, - const char *service_name, - const char *interface_name, - GError **error); -DBusGProxy* dbus_gproxy_new_for_object_path (DBusConnection *connection, - const char *path, - const char *interface_name); -DBusGProxy* dbus_gproxy_new_for_interface (DBusConnection *connection, - const char *interface_name); -void dbus_gproxy_ref (DBusGProxy *proxy); -void dbus_gproxy_unref (DBusGProxy *proxy); -gboolean dbus_gproxy_connect_signal (DBusGProxy *proxy, - const char *signal_name, - GCallback callback, - void *data, - GFreeFunc free_data_func, - GError **error); -DBusPendingCall* dbus_gproxy_begin_call (DBusGProxy *proxy, - const char *method, - int first_arg_type, - ...); -gboolean dbus_gproxy_end_call (DBusGProxy *proxy, - DBusPendingCall *pending, - GError **error, - int first_arg_type, - ...); -void dbus_gproxy_oneway_call (DBusGProxy *proxy, - const char *method, - int first_arg_type, - ...); -void dbus_gproxy_send (DBusGProxy *proxy, - DBusMessage *message, - dbus_uint32_t *client_serial); - - -G_END_DECLS - -#endif /* DBUS_GPROXY_H */ -- cgit From 4be7b14fce835a30b312bfed1492234bf1e0f316 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Mon, 22 Sep 2003 23:50:52 +0000 Subject: 2003-09-22 Havoc Pennington * glib/dbus-gproxy.c (dbus_gproxy_manager_get): implement --- glib/dbus-gproxy.c | 69 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 17 deletions(-) (limited to 'glib') diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c index 96a27888..57cdab2f 100644 --- a/glib/dbus-gproxy.c +++ b/glib/dbus-gproxy.c @@ -37,28 +37,61 @@ typedef struct { GStaticMutex lock; /**< Thread lock */ int refcount; /**< Reference count */ - + DBusConnection *connection; /**< Connection we're associated with. */ } DBusGProxyManager; - /** Lock the DBusGProxyManager */ #define LOCK_MANAGER(mgr) (g_static_mutex_lock (&(mgr)->lock)) /** Unlock the DBusGProxyManager */ #define UNLOCK_MANAGER(mgr) (g_static_mutex_unlock (&(mgr)->lock)) +static int gproxy_manager_slot = -1; + +/* Lock controlling get/set manager as data on each connection */ +static GStaticMutex connection_gproxy_lock = G_STATIC_MUTEX_INIT; + +static void dbus_gproxy_manager_ref (DBusGProxyManager *manager); + static DBusGProxyManager* -dbus_gproxy_manager_new (void) +dbus_gproxy_manager_get (DBusConnection *connection) { DBusGProxyManager *manager; + dbus_connection_allocate_data_slot (&gproxy_manager_slot); + if (gproxy_manager_slot < 0) + g_error ("out of memory"); + + g_static_mutex_lock (&connection_gproxy_lock); + + manager = dbus_connection_get_data (connection, gproxy_manager_slot); + if (manager != NULL) + { + dbus_connection_free_data_slot (&gproxy_manager_slot); + dbus_gproxy_manager_ref (manager); + g_static_mutex_unlock (&connection_gproxy_lock); + return manager; + } + manager = g_new0 (DBusGProxyManager, 1); manager->refcount = 1; + manager->connection = connection; g_static_mutex_init (&manager->lock); + /* Proxy managers keep the connection alive, which means that + * DBusGProxy indirectly does. To free a connection you have to free + * all the proxies referring to it. + */ + dbus_connection_ref (manager->connection); + + dbus_connection_set_data (connection, gproxy_manager_slot, + manager, NULL); + + g_static_mutex_unlock (&connection_gproxy_lock); + return manager; } @@ -89,7 +122,18 @@ dbus_gproxy_manager_unref (DBusGProxyManager *manager) g_static_mutex_free (&manager->lock); + g_static_mutex_lock (&connection_gproxy_lock); + + dbus_connection_set_data (manager->connection, + gproxy_manager_slot, + NULL, NULL); + + g_static_mutex_unlock (&connection_gproxy_lock); + + dbus_connection_unref (manager->connection); g_free (manager); + + dbus_connection_free_data_slot (&gproxy_manager_slot); } else { @@ -97,14 +141,6 @@ dbus_gproxy_manager_unref (DBusGProxyManager *manager) } } -static DBusGProxyManager* -dbus_gproxy_manager_get_for_connection (DBusConnection *connection) -{ - /* FIXME */ - - return NULL; -} - /** * Internals of DBusGProxy */ @@ -112,7 +148,7 @@ struct DBusGProxy { GStaticMutex lock; /**< Thread lock */ int refcount; /**< Reference count */ - DBusConnection *connection; /**< Connection to communicate over */ + DBusGProxyManager *manager; /**< Proxy manager */ char *service; /**< Service messages go to or NULL */ char *path; /**< Path messages go to or NULL */ char *interface; /**< Interface messages go to or NULL */ @@ -131,8 +167,7 @@ _dbus_gproxy_new (DBusConnection *connection) proxy = g_new0 (DBusGProxy, 1); proxy->refcount = 1; - proxy->connection = connection; - dbus_connection_ref (connection); + proxy->manager = dbus_gproxy_manager_get (connection); g_static_mutex_init (&proxy->lock); @@ -224,7 +259,7 @@ dbus_gproxy_unref (DBusGProxy *proxy) { UNLOCK_PROXY (proxy); - dbus_connection_unref (proxy->connection); + dbus_gproxy_manager_unref (proxy->manager); g_free (proxy->service); g_free (proxy->path); g_free (proxy->interface); @@ -282,7 +317,7 @@ dbus_gproxy_begin_call (DBusGProxy *proxy, goto oom; va_end (args); - if (!dbus_connection_send_with_reply (proxy->connection, + if (!dbus_connection_send_with_reply (proxy->manager->connection, message, &pending, -1)) @@ -409,7 +444,7 @@ dbus_gproxy_send (DBusGProxy *proxy, g_error ("Out of memory"); } - if (!dbus_connection_send (proxy->connection, message, client_serial)) + if (!dbus_connection_send (proxy->manager->connection, message, client_serial)) g_error ("Out of memory\n"); UNLOCK_PROXY (proxy); -- cgit From 0a34a4400619034e2be47f4387edf0204185d38b Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Tue, 23 Sep 2003 04:20:06 +0000 Subject: 2003-09-23 Havoc Pennington * glib/dbus-gproxy.c (struct DBusGProxy): convert to a GObject subclass. This means dropping the transparent thread safety of the proxy; you now need a separate proxy per-thread, or your own locking on the proxy. Probably right anyway. (dbus_gproxy_ref, dbus_gproxy_unref): nuke, just use g_object_ref --- glib/dbus-glib.h | 20 ++++++- glib/dbus-gproxy.c | 160 ++++++++++++++++++++++++++--------------------------- 2 files changed, 98 insertions(+), 82 deletions(-) (limited to 'glib') diff --git a/glib/dbus-glib.h b/glib/dbus-glib.h index 7fd88e71..556d896e 100644 --- a/glib/dbus-glib.h +++ b/glib/dbus-glib.h @@ -87,6 +87,17 @@ void dbus_connection_register_g_object (DBusConnection *connection, typedef struct DBusGProxy DBusGProxy; +typedef struct DBusGProxyClass DBusGProxyClass; + + +#define DBUS_TYPE_GPROXY (dbus_gproxy_get_type ()) +#define DBUS_GPROXY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), DBUS_TYPE_GPROXY, DBusGProxy)) +#define DBUS_GPROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DBUS_TYPE_GPROXY, DBusGProxyClass)) +#define DBUS_IS_GPROXY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), DBUS_TYPE_GPROXY)) +#define DBUS_IS_GPROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DBUS_TYPE_GPROXY)) +#define DBUS_GPROXY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DBUS_TYPE_GPROXY, DBusGProxyClass)) + +GType dbus_gproxy_get_type (void) G_GNUC_CONST; DBusGProxy* dbus_gproxy_new_for_service (DBusConnection *connection, const char *service_name, @@ -104,11 +115,16 @@ DBusGProxy* dbus_gproxy_new_for_peer (DBusConnection *connection void dbus_gproxy_ref (DBusGProxy *proxy); void dbus_gproxy_unref (DBusGProxy *proxy); gboolean dbus_gproxy_connect_signal (DBusGProxy *proxy, + const char *interface_name, const char *signal_name, GCallback callback, void *data, - GFreeFunc free_data_func, - GError **error); + GFreeFunc free_data_func); +gboolean dbus_gproxy_disconnect_signal (DBusGProxy *proxy, + const char *interface_name, + const char *signal_name, + GCallback callback, + void *data); DBusPendingCall* dbus_gproxy_begin_call (DBusGProxy *proxy, const char *method, int first_arg_type, diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c index 57cdab2f..05a073bf 100644 --- a/glib/dbus-gproxy.c +++ b/glib/dbus-gproxy.c @@ -146,32 +146,55 @@ dbus_gproxy_manager_unref (DBusGProxyManager *manager) */ struct DBusGProxy { - GStaticMutex lock; /**< Thread lock */ - int refcount; /**< Reference count */ + GObject parent; + DBusGProxyManager *manager; /**< Proxy manager */ - char *service; /**< Service messages go to or NULL */ - char *path; /**< Path messages go to or NULL */ - char *interface; /**< Interface messages go to or NULL */ + char *service; /**< Service messages go to or NULL */ + char *path; /**< Path messages go to or NULL */ + char *interface; /**< Interface messages go to or NULL */ }; -/** Lock the DBusGProxy */ -#define LOCK_PROXY(proxy) (g_static_mutex_lock (&(proxy)->lock)) -/** Unlock the DBusGProxy */ -#define UNLOCK_PROXY(proxy) (g_static_mutex_unlock (&(proxy)->lock)) +struct DBusGProxyClass +{ + GObjectClass parent_class; +}; -static DBusGProxy* -_dbus_gproxy_new (DBusConnection *connection) +static void dbus_gproxy_init (DBusGProxy *proxy); +static void dbus_gproxy_class_init (DBusGProxyClass *klass); +static void dbus_gproxy_finalize (GObject *object); + +static void *parent_class; + +static void +dbus_gproxy_init (DBusGProxy *proxy) { - DBusGProxy *proxy; + /* Nothing */ +} - proxy = g_new0 (DBusGProxy, 1); +static void +dbus_gproxy_class_init (DBusGProxyClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); - proxy->refcount = 1; - proxy->manager = dbus_gproxy_manager_get (connection); + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = dbus_gproxy_finalize; +} - g_static_mutex_init (&proxy->lock); +static void +dbus_gproxy_finalize (GObject *object) +{ + DBusGProxy *proxy; + + proxy = DBUS_GPROXY (object); + + if (proxy->manager) + dbus_gproxy_manager_unref (proxy->manager); + g_free (proxy->service); + g_free (proxy->path); + g_free (proxy->interface); - return proxy; + G_OBJECT_CLASS (parent_class)->finalize (object); } /** @} End of DBusGLibInternals */ @@ -180,6 +203,39 @@ _dbus_gproxy_new (DBusConnection *connection) * @{ */ +/** + * Standard GObject get_type() function for DBusGProxy. + * + * @returns type ID for DBusGProxy class + */ +GType +dbus_gproxy_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (DBusGProxyClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) dbus_gproxy_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (DBusGProxy), + 0, /* n_preallocs */ + (GInstanceInitFunc) dbus_gproxy_init, + }; + + object_type = g_type_register_static (G_TYPE_OBJECT, + "DBusGProxy", + &object_info, 0); + } + + return object_type; +} + /** * Creates a new proxy for a remote interface. Method calls and signal * connections over this proxy will go to the service owner; the @@ -211,8 +267,14 @@ dbus_gproxy_new_for_service (DBusConnection *connection, g_return_val_if_fail (path_name != NULL, NULL); g_return_val_if_fail (interface_name != NULL, NULL); - proxy = _dbus_gproxy_new (connection); + proxy = g_object_new (DBUS_TYPE_GPROXY, NULL); + /* These should all be construct-only mandatory properties, + * for now we just don't let people use g_object_new(). + */ + + proxy->manager = dbus_gproxy_manager_get (connection); + proxy->service = g_strdup (service_name); proxy->path = g_strdup (path_name); proxy->interface = g_strdup (interface_name); @@ -220,58 +282,6 @@ dbus_gproxy_new_for_service (DBusConnection *connection, return proxy; } -/** - * Increment reference count on proxy object. - * - * @todo use GAtomic to avoid locking - * - * @param proxy the proxy - */ -void -dbus_gproxy_ref (DBusGProxy *proxy) -{ - g_return_if_fail (proxy != NULL); - - LOCK_PROXY (proxy); - - proxy->refcount += 1; - - UNLOCK_PROXY (proxy); -} - -/** - * Decrement reference count on proxy object. - * - * @todo use GAtomic to avoid locking - * - * @param proxy the proxy - */ -void -dbus_gproxy_unref (DBusGProxy *proxy) -{ - g_return_if_fail (proxy != NULL); - - LOCK_PROXY (proxy); - - proxy->refcount -= 1; - - if (proxy->refcount == 0) - { - UNLOCK_PROXY (proxy); - - dbus_gproxy_manager_unref (proxy->manager); - g_free (proxy->service); - g_free (proxy->path); - g_free (proxy->interface); - g_static_mutex_free (&proxy->lock); - g_free (proxy); - } - else - { - UNLOCK_PROXY (proxy); - } -} - /** * Invokes a method on a remote interface. This function does not * block; instead it returns an opaque #DBusPendingCall object that @@ -302,7 +312,6 @@ dbus_gproxy_begin_call (DBusGProxy *proxy, va_list args; g_return_val_if_fail (proxy != NULL, NULL); - LOCK_PROXY (proxy); message = dbus_message_new_method_call (proxy->service, proxy->path, @@ -322,8 +331,6 @@ dbus_gproxy_begin_call (DBusGProxy *proxy, &pending, -1)) goto oom; - - UNLOCK_PROXY (proxy); return pending; @@ -375,8 +382,6 @@ dbus_gproxy_end_call (DBusGProxy *proxy, g_return_val_if_fail (proxy != NULL, FALSE); g_return_val_if_fail (pending != NULL, FALSE); - - LOCK_PROXY (proxy); dbus_pending_call_block (pending); message = dbus_pending_call_get_reply (pending); @@ -392,8 +397,6 @@ dbus_gproxy_end_call (DBusGProxy *proxy, } va_end (args); - UNLOCK_PROXY (proxy); - return TRUE; error: @@ -426,7 +429,6 @@ dbus_gproxy_send (DBusGProxy *proxy, dbus_uint32_t *client_serial) { g_return_if_fail (proxy != NULL); - LOCK_PROXY (proxy); if (proxy->service) { @@ -446,8 +448,6 @@ dbus_gproxy_send (DBusGProxy *proxy, if (!dbus_connection_send (proxy->manager->connection, message, client_serial)) g_error ("Out of memory\n"); - - UNLOCK_PROXY (proxy); } /** @} End of DBusGLib public */ -- cgit From cefe445bea082f0891142ac4b746893e4ffb7d1f Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Tue, 23 Sep 2003 05:04:51 +0000 Subject: trivial header change --- glib/dbus-glib.h | 51 ++++++++++++++++++++++++--------------------------- glib/dbus-gproxy.c | 23 +++++++++++++++++++++++ 2 files changed, 47 insertions(+), 27 deletions(-) (limited to 'glib') diff --git a/glib/dbus-glib.h b/glib/dbus-glib.h index 556d896e..a391c4a1 100644 --- a/glib/dbus-glib.h +++ b/glib/dbus-glib.h @@ -111,36 +111,33 @@ DBusGProxy* dbus_gproxy_new_for_service_owner (DBusConnection *connection DBusGProxy* dbus_gproxy_new_for_peer (DBusConnection *connection, const char *path_name, const char *interface_name); - -void dbus_gproxy_ref (DBusGProxy *proxy); -void dbus_gproxy_unref (DBusGProxy *proxy); -gboolean dbus_gproxy_connect_signal (DBusGProxy *proxy, - const char *interface_name, - const char *signal_name, - GCallback callback, - void *data, - GFreeFunc free_data_func); -gboolean dbus_gproxy_disconnect_signal (DBusGProxy *proxy, - const char *interface_name, - const char *signal_name, - GCallback callback, - void *data); -DBusPendingCall* dbus_gproxy_begin_call (DBusGProxy *proxy, - const char *method, - int first_arg_type, +void dbus_gproxy_connect_signal (DBusGProxy *proxy, + const char *interface_name, + const char *signal_name, + GCallback callback, + void *data, + GFreeFunc free_data_func); +void dbus_gproxy_disconnect_signal (DBusGProxy *proxy, + const char *interface_name, + const char *signal_name, + GCallback callback, + void *data); +DBusPendingCall* dbus_gproxy_begin_call (DBusGProxy *proxy, + const char *method, + int first_arg_type, ...); -gboolean dbus_gproxy_end_call (DBusGProxy *proxy, - DBusPendingCall *pending, - GError **error, - int first_arg_type, +gboolean dbus_gproxy_end_call (DBusGProxy *proxy, + DBusPendingCall *pending, + GError **error, + int first_arg_type, ...); -void dbus_gproxy_oneway_call (DBusGProxy *proxy, - const char *method, - int first_arg_type, +void dbus_gproxy_oneway_call (DBusGProxy *proxy, + const char *method, + int first_arg_type, ...); -void dbus_gproxy_send (DBusGProxy *proxy, - DBusMessage *message, - dbus_uint32_t *client_serial); +void dbus_gproxy_send (DBusGProxy *proxy, + DBusMessage *message, + dbus_uint32_t *client_serial); #undef DBUS_INSIDE_DBUS_GLIB_H diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c index 05a073bf..f27eb6d0 100644 --- a/glib/dbus-gproxy.c +++ b/glib/dbus-gproxy.c @@ -450,6 +450,29 @@ dbus_gproxy_send (DBusGProxy *proxy, g_error ("Out of memory\n"); } +void +dbus_gproxy_connect_signal (DBusGProxy *proxy, + const char *interface_name, + const char *signal_name, + GCallback callback, + void *data, + GFreeFunc free_data_func) +{ + + +} + +void +dbus_gproxy_disconnect_signal (DBusGProxy *proxy, + const char *interface_name, + const char *signal_name, + GCallback callback, + void *data) +{ + + +} + /** @} End of DBusGLib public */ #ifdef DBUS_BUILD_TESTS -- cgit From 52f275a7f43a78f981d0ccc85d5882ff4c356bdd Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Tue, 23 Sep 2003 23:47:09 +0000 Subject: 2003-09-23 Havoc Pennington * glib/dbus-gproxy.c (dbus_gproxy_connect_signal): implement (dbus_gproxy_disconnect_signal): implement (dbus_gproxy_manager_remove_signal_match): implement (dbus_gproxy_manager_add_signal_match): implement (dbus_gproxy_oneway_call): implement --- glib/dbus-glib.h | 81 +++---- glib/dbus-gmain.c | 37 ++++ glib/dbus-gproxy.c | 629 +++++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 662 insertions(+), 85 deletions(-) (limited to 'glib') diff --git a/glib/dbus-glib.h b/glib/dbus-glib.h index a391c4a1..79c1e116 100644 --- a/glib/dbus-glib.h +++ b/glib/dbus-glib.h @@ -34,6 +34,11 @@ G_BEGIN_DECLS GQuark dbus_g_error_quark (void); #define DBUS_GERROR dbus_g_error_quark () +#define DBUS_TYPE_CONNECTION (dbus_connection_get_g_type ()) +#define DBUS_TYPE_MESSAGE (dbus_message_get_g_type ()) +GType dbus_connection_get_g_type (void) G_GNUC_CONST; +GType dbus_message_get_g_type (void) G_GNUC_CONST; + typedef enum { /* FIXME map all the DBUS_ERROR to DBUS_GERROR, should @@ -89,6 +94,9 @@ void dbus_connection_register_g_object (DBusConnection *connection, typedef struct DBusGProxy DBusGProxy; typedef struct DBusGProxyClass DBusGProxyClass; +typedef void (* DBusGProxySignalHandler) (DBusGProxy *proxy, + DBusMessage *signal, + void *user_data); #define DBUS_TYPE_GPROXY (dbus_gproxy_get_type ()) #define DBUS_GPROXY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), DBUS_TYPE_GPROXY, DBusGProxy)) @@ -97,47 +105,46 @@ typedef struct DBusGProxyClass DBusGProxyClass; #define DBUS_IS_GPROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DBUS_TYPE_GPROXY)) #define DBUS_GPROXY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DBUS_TYPE_GPROXY, DBusGProxyClass)) -GType dbus_gproxy_get_type (void) G_GNUC_CONST; -DBusGProxy* dbus_gproxy_new_for_service (DBusConnection *connection, - const char *service_name, - const char *path_name, - const char *interface_name); -DBusGProxy* dbus_gproxy_new_for_service_owner (DBusConnection *connection, - const char *service_name, - const char *path_name, - const char *interface_name, - GError **error); -DBusGProxy* dbus_gproxy_new_for_peer (DBusConnection *connection, - const char *path_name, - const char *interface_name); -void dbus_gproxy_connect_signal (DBusGProxy *proxy, - const char *interface_name, - const char *signal_name, - GCallback callback, - void *data, - GFreeFunc free_data_func); -void dbus_gproxy_disconnect_signal (DBusGProxy *proxy, - const char *interface_name, - const char *signal_name, - GCallback callback, - void *data); -DBusPendingCall* dbus_gproxy_begin_call (DBusGProxy *proxy, - const char *method, - int first_arg_type, +GType dbus_gproxy_get_type (void) G_GNUC_CONST; +DBusGProxy* dbus_gproxy_new_for_service (DBusConnection *connection, + const char *service_name, + const char *path_name, + const char *interface_name); +DBusGProxy* dbus_gproxy_new_for_service_owner (DBusConnection *connection, + const char *service_name, + const char *path_name, + const char *interface_name, + GError **error); +DBusGProxy* dbus_gproxy_new_for_peer (DBusConnection *connection, + const char *path_name, + const char *interface_name); +void dbus_gproxy_connect_signal (DBusGProxy *proxy, + const char *signal_name, + DBusGProxySignalHandler handler, + void *data, + GFreeFunc free_data_func); +void dbus_gproxy_disconnect_signal (DBusGProxy *proxy, + const char *signal_name, + DBusGProxySignalHandler handler, + void *data); +DBusPendingCall* dbus_gproxy_begin_call (DBusGProxy *proxy, + const char *method, + int first_arg_type, ...); -gboolean dbus_gproxy_end_call (DBusGProxy *proxy, - DBusPendingCall *pending, - GError **error, - int first_arg_type, +gboolean dbus_gproxy_end_call (DBusGProxy *proxy, + DBusPendingCall *pending, + GError **error, + int first_arg_type, ...); -void dbus_gproxy_oneway_call (DBusGProxy *proxy, - const char *method, - int first_arg_type, +void dbus_gproxy_oneway_call (DBusGProxy *proxy, + const char *method, + int first_arg_type, ...); -void dbus_gproxy_send (DBusGProxy *proxy, - DBusMessage *message, - dbus_uint32_t *client_serial); +void dbus_gproxy_send (DBusGProxy *proxy, + DBusMessage *message, + dbus_uint32_t *client_serial); + #undef DBUS_INSIDE_DBUS_GLIB_H diff --git a/glib/dbus-gmain.c b/glib/dbus-gmain.c index 2e5604dc..54a2d462 100644 --- a/glib/dbus-gmain.c +++ b/glib/dbus-gmain.c @@ -535,6 +535,43 @@ dbus_set_g_error (GError **gerror, derror->name, derror->message); } +/** + * Get the GLib type ID for a DBusConnection boxed type. + * + * @returns GLib type + */ +GType +dbus_connection_get_g_type (void) +{ + static GType our_type = 0; + + if (our_type == 0) + our_type = g_boxed_type_register_static ("DBusConnection", + (GBoxedCopyFunc) dbus_connection_ref, + (GBoxedFreeFunc) dbus_connection_unref); + + return our_type; +} + +/** + * Get the GLib type ID for a DBusMessage boxed type. + * + * @returns GLib type + */ +GType +dbus_message_get_g_type (void) +{ + static GType our_type = 0; + + if (our_type == 0) + our_type = g_boxed_type_register_static ("DBusMessage", + (GBoxedCopyFunc) dbus_message_ref, + (GBoxedFreeFunc) dbus_message_unref); + + return our_type; +} + + /** @} */ /* end of public API */ #ifdef DBUS_BUILD_TESTS diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c index f27eb6d0..ebcbb5d4 100644 --- a/glib/dbus-gproxy.c +++ b/glib/dbus-gproxy.c @@ -21,6 +21,7 @@ * */ #include "dbus-glib.h" +#include /** * @addtogroup DBusGLibInternals @@ -28,19 +29,69 @@ * @{ */ +typedef struct DBusGProxyManager DBusGProxyManager; + +/** + * Internals of DBusGProxy + */ +struct DBusGProxy +{ + GObject parent; /**< Parent instance */ + + DBusGProxyManager *manager; /**< Proxy manager */ + char *service; /**< Service messages go to or NULL */ + char *path; /**< Path messages go to or NULL */ + char *interface; /**< Interface messages go to or NULL */ +}; + +struct DBusGProxyClass +{ + GObjectClass parent_class; +}; + +static void dbus_gproxy_init (DBusGProxy *proxy); +static void dbus_gproxy_class_init (DBusGProxyClass *klass); +static void dbus_gproxy_finalize (GObject *object); +static void dbus_gproxy_emit_received (DBusGProxy *proxy, + DBusMessage *message); + + +/** + * A list of proxies with a given service+path+interface, used to route incoming + * signals. + */ +typedef struct +{ + GSList *proxies; + + char name[4]; /**< service (empty string for none), nul byte, + * path, nul byte, + * interface, nul byte + */ + +} DBusGProxyList; + /** * DBusGProxyManager's primary task is to route signals to the proxies * those signals are emitted on. In order to do this it also has to * track the owners of the services proxies are bound to. */ -typedef struct +struct DBusGProxyManager { GStaticMutex lock; /**< Thread lock */ int refcount; /**< Reference count */ DBusConnection *connection; /**< Connection we're associated with. */ - -} DBusGProxyManager; + GHashTable *proxy_lists; /**< Hash used to route incoming signals + * and iterate over proxies + */ + +}; + +static void dbus_gproxy_manager_ref (DBusGProxyManager *manager); +static DBusHandlerResult dbus_gproxy_manager_filter (DBusConnection *connection, + DBusMessage *message, + void *user_data); /** Lock the DBusGProxyManager */ #define LOCK_MANAGER(mgr) (g_static_mutex_lock (&(mgr)->lock)) @@ -52,8 +103,6 @@ static int gproxy_manager_slot = -1; /* Lock controlling get/set manager as data on each connection */ static GStaticMutex connection_gproxy_lock = G_STATIC_MUTEX_INIT; -static void dbus_gproxy_manager_ref (DBusGProxyManager *manager); - static DBusGProxyManager* dbus_gproxy_manager_get (DBusConnection *connection) { @@ -90,6 +139,9 @@ dbus_gproxy_manager_get (DBusConnection *connection) dbus_connection_set_data (connection, gproxy_manager_slot, manager, NULL); + dbus_connection_add_filter (connection, dbus_gproxy_manager_filter, + manager, NULL); + g_static_mutex_unlock (&connection_gproxy_lock); return manager; @@ -119,10 +171,19 @@ dbus_gproxy_manager_unref (DBusGProxyManager *manager) if (manager->refcount == 0) { UNLOCK_MANAGER (manager); + + if (manager->proxy_lists) + { + g_hash_table_destroy (manager->proxy_lists); + manager->proxy_lists = NULL; + } g_static_mutex_free (&manager->lock); g_static_mutex_lock (&connection_gproxy_lock); + + dbus_connection_remove_filter (manager->connection, dbus_gproxy_manager_filter, + manager); dbus_connection_set_data (manager->connection, gproxy_manager_slot, @@ -141,29 +202,340 @@ dbus_gproxy_manager_unref (DBusGProxyManager *manager) } } -/** - * Internals of DBusGProxy - */ -struct DBusGProxy +static guint +tristring_hash (gconstpointer key) { - GObject parent; + const char *p = key; + guint h = *p; + + if (h) + { + for (p += 1; *p != '\0'; p++) + h = (h << 5) - h + *p; + } + + /* skip nul and do the next substring */ + for (p += 1; *p != '\0'; p++) + h = (h << 5) - h + *p; + + /* skip nul again and another substring */ + for (p += 1; *p != '\0'; p++) + h = (h << 5) - h + *p; - DBusGProxyManager *manager; /**< Proxy manager */ - char *service; /**< Service messages go to or NULL */ - char *path; /**< Path messages go to or NULL */ - char *interface; /**< Interface messages go to or NULL */ -}; + return h; +} -struct DBusGProxyClass +static gboolean +strequal_len (const char *a, + const char *b, + size_t *lenp) { - GObjectClass parent_class; -}; + size_t a_len; + size_t b_len; + + a_len = strlen (a); + b_len = strlen (b); + + if (a_len != b_len) + return FALSE; + + if (memcmp (a, b, a_len) != 0) + return FALSE; + + *lenp = a_len; + + return TRUE; +} + +static gboolean +tristring_equal (gconstpointer a, + gconstpointer b) +{ + const char *ap = a; + const char *bp = b; + size_t len; + + if (!strequal_len (ap, bp, &len)) + return FALSE; + + ap += len + 1; + bp += len + 1; + + if (!strequal_len (ap, bp, &len)) + return FALSE; + + ap += len + 1; + bp += len + 1; + + if (strcmp (ap, bp) != 0) + return FALSE; + + return TRUE; +} + +static char* +tristring_alloc_from_strings (size_t padding_before, + const char *service, + const char *path, + const char *interface) +{ + size_t service_len, iface_len, path_len, len; + char *tri; + + if (service) + service_len = strlen (service); + else + service_len = 0; + + path_len = strlen (path); + + iface_len = strlen (interface); + + tri = g_malloc (padding_before + service_len + path_len + iface_len + 3); + + len = padding_before; + + if (service) + memcpy (&tri[len], service, service_len); + + len += service_len; + tri[len] = '\0'; + len += 1; + + g_assert (len == (padding_before + service_len + 1)); + + memcpy (&tri[len], path, path_len); + len += path_len; + tri[len] = '\0'; + len += 1; + + g_assert (len == (padding_before + service_len + path_len + 2)); + + memcpy (&tri[len], interface, iface_len); + len += iface_len; + tri[len] = '\0'; + len += 1; + + g_assert (len == (padding_before + service_len + path_len + iface_len + 3)); + + return tri; +} + +static char* +tristring_from_proxy (DBusGProxy *proxy) +{ + return tristring_alloc_from_strings (0, + proxy->service, + proxy->path, + proxy->interface); +} + +static char* +tristring_from_message (DBusMessage *message) +{ + return tristring_alloc_from_strings (0, + dbus_message_get_sender (message), + dbus_message_get_path (message), + dbus_message_get_interface (message)); +} + +static DBusGProxyList* +gproxy_list_new (DBusGProxy *first_proxy) +{ + DBusGProxyList *list; + + list = (void*) tristring_alloc_from_strings (G_STRUCT_OFFSET (DBusGProxyList, name), + first_proxy->service, + first_proxy->path, + first_proxy->interface); + list->proxies = NULL; + + return list; +} + +static void +gproxy_list_free (DBusGProxyList *list) +{ + /* we don't hold a reference to the proxies in the list, + * as they ref the GProxyManager + */ + g_slist_free (list->proxies); + + g_free (list); +} + +static char* +gproxy_get_match_rule (DBusGProxy *proxy) +{ + /* FIXME Some sort of escaping is required here I think */ + + if (proxy->service) + return g_strdup_printf ("type='signal',service='%s',path='%s',interface='%s'", + proxy->service, proxy->path, proxy->interface); + else + return g_strdup_printf ("type='signal',path='%s',interface='%s'", + proxy->path, proxy->interface); +} + +static void +dbus_gproxy_manager_register (DBusGProxyManager *manager, + DBusGProxy *proxy) +{ + DBusGProxyList *list; + + LOCK_MANAGER (manager); + + if (manager->proxy_lists == NULL) + { + list = NULL; + manager->proxy_lists = g_hash_table_new_full (tristring_hash, + tristring_equal, + NULL, + (GFreeFunc) gproxy_list_free); + } + else + { + char *tri; + + tri = tristring_from_proxy (proxy); + + list = g_hash_table_lookup (manager->proxy_lists, tri); + + g_free (tri); + } + + if (list == NULL) + { + list = gproxy_list_new (proxy); + + g_hash_table_replace (manager->proxy_lists, + list->name, list); + } + + if (list->proxies == NULL) + { + /* We have to add the match rule to the server, + * but FIXME only if the server is a message bus, + * not if it's a peer. + */ + char *rule; + + rule = gproxy_get_match_rule (proxy); + + /* We don't check for errors; it's not like anyone would handle them, + * and we don't want a round trip here. + */ + dbus_bus_add_match (manager->connection, + rule, NULL); + + g_free (rule); + } + + g_assert (g_slist_find (list->proxies, proxy) == NULL); + + list->proxies = g_slist_prepend (list->proxies, proxy); + + UNLOCK_MANAGER (manager); +} + +static void +dbus_gproxy_manager_unregister (DBusGProxyManager *manager, + DBusGProxy *proxy) +{ + DBusGProxyList *list; + char *tri; + + LOCK_MANAGER (manager); + + if (manager->proxy_lists == NULL) + { + g_warning ("Trying to disconnect a signal on a proxy but none are connected\n"); + return; + } + + tri = tristring_from_proxy (proxy); + + list = g_hash_table_lookup (manager->proxy_lists, tri); + + g_free (tri); + + if (list == NULL) + { + g_warning ("Trying to disconnect a signal on a proxy but none are connected\n"); + return; + } + + g_assert (g_slist_find (list->proxies, proxy) != NULL); + + list->proxies = g_slist_remove (list->proxies, proxy); + + g_assert (g_slist_find (list->proxies, proxy) == NULL); + + UNLOCK_MANAGER (manager); +} + +static DBusHandlerResult +dbus_gproxy_manager_filter (DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + DBusGProxyManager *manager; + + manager = user_data; + + if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (dbus_message_is_signal (message, + DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, + "Disconnected")) + { + /* FIXME g_object_run_dispose() all the proxies; should proxies have + * a "destroy" signal? + */ + } + else + { + char *tri; + DBusGProxyList *list; + + tri = tristring_from_message (message); -static void dbus_gproxy_init (DBusGProxy *proxy); -static void dbus_gproxy_class_init (DBusGProxyClass *klass); -static void dbus_gproxy_finalize (GObject *object); + if (manager->proxy_lists) + list = g_hash_table_lookup (manager->proxy_lists, tri); + else + list = NULL; + + g_free (tri); + + if (list != NULL) + { + /* FIXME Emit the signal on each proxy in the list */ + + + } + } + + /* "Handling" signals doesn't make sense, they are for everyone + * who cares + */ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + + + +/* ---------- DBusGProxy -------------- */ + + + +enum +{ + RECEIVED, + LAST_SIGNAL +}; static void *parent_class; +static guint signals[LAST_SIGNAL] = { 0 }; static void dbus_gproxy_init (DBusGProxy *proxy) @@ -179,6 +551,16 @@ dbus_gproxy_class_init (DBusGProxyClass *klass) parent_class = g_type_class_peek_parent (klass); object_class->finalize = dbus_gproxy_finalize; + + signals[RECEIVED] = + g_signal_new ("received", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, 1, + DBUS_TYPE_MESSAGE); } static void @@ -189,7 +571,11 @@ dbus_gproxy_finalize (GObject *object) proxy = DBUS_GPROXY (object); if (proxy->manager) - dbus_gproxy_manager_unref (proxy->manager); + { + dbus_gproxy_manager_unregister (proxy->manager, proxy); + dbus_gproxy_manager_unref (proxy->manager); + } + g_free (proxy->service); g_free (proxy->path); g_free (proxy->interface); @@ -197,6 +583,53 @@ dbus_gproxy_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static char* +create_signal_detail (const char *interface, + const char *signal) +{ + GString *str; + + str = g_string_new (interface); + + g_string_append (str, "."); + + g_string_append (str, signal); + + return g_string_free (str, FALSE); +} + +static void +dbus_gproxy_emit_received (DBusGProxy *proxy, + DBusMessage *message) +{ + const char *interface; + const char *signal; + char *detail; + GQuark q; + + interface = dbus_message_get_interface (message); + signal = dbus_message_get_member (message); + + g_assert (interface != NULL); + g_assert (signal != NULL); + + detail = create_signal_detail (interface, signal); + + /* If the quark isn't preexisting, there's no way there + * are any handlers connected. We don't want to create + * extra quarks for every possible signal. + */ + q = g_quark_try_string (detail); + + if (q != 0) + g_signal_emit (G_OBJECT (proxy), + signals[RECEIVED], + q, + message); + + g_free (detail); +} + /** @} End of DBusGLibInternals */ /** @addtogroup DBusGLib @@ -236,6 +669,33 @@ dbus_gproxy_get_type (void) return object_type; } +static DBusGProxy* +dbus_gproxy_new (DBusConnection *connection, + const char *service_name, + const char *path_name, + const char *interface_name) +{ + DBusGProxy *proxy; + + g_assert (connection != NULL); + + proxy = g_object_new (DBUS_TYPE_GPROXY, NULL); + + /* These should all be construct-only mandatory properties, + * for now we just don't let people use g_object_new(). + */ + + proxy->manager = dbus_gproxy_manager_get (connection); + + proxy->service = g_strdup (service_name); + proxy->path = g_strdup (path_name); + proxy->interface = g_strdup (interface_name); + + dbus_gproxy_manager_register (proxy->manager, proxy); + + return proxy; +} + /** * Creates a new proxy for a remote interface. Method calls and signal * connections over this proxy will go to the service owner; the @@ -267,17 +727,8 @@ dbus_gproxy_new_for_service (DBusConnection *connection, g_return_val_if_fail (path_name != NULL, NULL); g_return_val_if_fail (interface_name != NULL, NULL); - proxy = g_object_new (DBUS_TYPE_GPROXY, NULL); - - /* These should all be construct-only mandatory properties, - * for now we just don't let people use g_object_new(). - */ - - proxy->manager = dbus_gproxy_manager_get (connection); - - proxy->service = g_strdup (service_name); - proxy->path = g_strdup (path_name); - proxy->interface = g_strdup (interface_name); + proxy = dbus_gproxy_new (connection, service_name, + path_name, interface_name); return proxy; } @@ -311,7 +762,7 @@ dbus_gproxy_begin_call (DBusGProxy *proxy, DBusMessage *message; va_list args; - g_return_val_if_fail (proxy != NULL, NULL); + g_return_val_if_fail (DBUS_IS_GPROXY (proxy), NULL); message = dbus_message_new_method_call (proxy->service, proxy->path, @@ -380,7 +831,7 @@ dbus_gproxy_end_call (DBusGProxy *proxy, va_list args; DBusError derror; - g_return_val_if_fail (proxy != NULL, FALSE); + g_return_val_if_fail (DBUS_IS_GPROXY (proxy), FALSE); g_return_val_if_fail (pending != NULL, FALSE); dbus_pending_call_block (pending); @@ -405,6 +856,52 @@ dbus_gproxy_end_call (DBusGProxy *proxy, return FALSE; } +/** + * Sends a method call message as with dbus_gproxy_begin_call(), but + * does not ask for a reply or allow you to receive one. + * + * @todo this particular function shouldn't die on out of memory, + * since you should be able to do a call with large arguments. + * + * @param proxy a proxy for a remote interface + * @param method the name of the method to invoke + * @param first_arg_type type of the first argument + */ +void +dbus_gproxy_oneway_call (DBusGProxy *proxy, + const char *method, + int first_arg_type, + ...) +{ + DBusMessage *message; + va_list args; + + g_return_if_fail (DBUS_IS_GPROXY (proxy)); + + message = dbus_message_new_method_call (proxy->service, + proxy->path, + proxy->interface, + method); + if (message == NULL) + goto oom; + + dbus_message_set_no_reply (message, TRUE); + + va_start (args, first_arg_type); + if (!dbus_message_append_args_valist (message, first_arg_type, + args)) + goto oom; + va_end (args); + + if (!dbus_connection_send (proxy->manager->connection, + message, + NULL)) + goto oom; + + oom: + g_error ("Out of memory"); +} + /** * Sends a message to the interface we're proxying for. Does not * block or wait for a reply. The message is only actually written out @@ -428,7 +925,7 @@ dbus_gproxy_send (DBusGProxy *proxy, DBusMessage *message, dbus_uint32_t *client_serial) { - g_return_if_fail (proxy != NULL); + g_return_if_fail (DBUS_IS_GPROXY (proxy)); if (proxy->service) { @@ -451,26 +948,62 @@ dbus_gproxy_send (DBusGProxy *proxy, } void -dbus_gproxy_connect_signal (DBusGProxy *proxy, - const char *interface_name, - const char *signal_name, - GCallback callback, - void *data, - GFreeFunc free_data_func) +dbus_gproxy_connect_signal (DBusGProxy *proxy, + const char *signal_name, + DBusGProxySignalHandler handler, + void *data, + GFreeFunc free_data_func) { + GClosure *closure; + char *detail; + g_return_if_fail (DBUS_IS_GPROXY (proxy)); + g_return_if_fail (signal_name != NULL); + g_return_if_fail (handler != NULL); + + detail = create_signal_detail (proxy->interface, signal_name); + + closure = g_cclosure_new (G_CALLBACK (handler), data, free_data_func); + g_signal_connect_closure_by_id (G_OBJECT (proxy), + signals[RECEIVED], + g_quark_from_string (detail), + closure, FALSE); + g_free (detail); } void -dbus_gproxy_disconnect_signal (DBusGProxy *proxy, - const char *interface_name, - const char *signal_name, - GCallback callback, - void *data) +dbus_gproxy_disconnect_signal (DBusGProxy *proxy, + const char *signal_name, + DBusGProxySignalHandler handler, + void *data) { + char *detail; + GQuark q; - + g_return_if_fail (DBUS_IS_GPROXY (proxy)); + g_return_if_fail (signal_name != NULL); + g_return_if_fail (handler != NULL); + + detail = create_signal_detail (proxy->interface, signal_name); + q = g_quark_try_string (detail); + g_free (detail); + + if (q == 0) + { + g_warning ("%s: No signal handlers for %s found on this DBusGProxy", + G_GNUC_FUNCTION, signal_name); + return; + } + + g_signal_handlers_disconnect_matched (G_OBJECT (proxy), + G_SIGNAL_MATCH_DETAIL | + G_SIGNAL_MATCH_FUNC | + G_SIGNAL_MATCH_DATA, + signals[RECEIVED], + q, + NULL, + G_CALLBACK (handler), data); } /** @} End of DBusGLib public */ -- cgit From 31881de7dafad50446d2b0c8c0c96aa87a70ba61 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 24 Sep 2003 02:58:14 +0000 Subject: 2003-09-23 Havoc Pennington * glib/dbus-gproxy.c (dbus_gproxy_manager_filter): implement --- glib/dbus-glib.h | 2 +- glib/dbus-gproxy.c | 258 +++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 242 insertions(+), 18 deletions(-) (limited to 'glib') diff --git a/glib/dbus-glib.h b/glib/dbus-glib.h index 79c1e116..46f4555d 100644 --- a/glib/dbus-glib.h +++ b/glib/dbus-glib.h @@ -123,7 +123,7 @@ void dbus_gproxy_connect_signal (DBusGProxy *pr const char *signal_name, DBusGProxySignalHandler handler, void *data, - GFreeFunc free_data_func); + GClosureNotify free_data_func); void dbus_gproxy_disconnect_signal (DBusGProxy *proxy, const char *signal_name, DBusGProxySignalHandler handler, diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c index ebcbb5d4..99900e4c 100644 --- a/glib/dbus-gproxy.c +++ b/glib/dbus-gproxy.c @@ -44,6 +44,9 @@ struct DBusGProxy char *interface; /**< Interface messages go to or NULL */ }; +/** + * Class struct for DBusGProxy + */ struct DBusGProxyClass { GObjectClass parent_class; @@ -52,6 +55,8 @@ struct DBusGProxyClass static void dbus_gproxy_init (DBusGProxy *proxy); static void dbus_gproxy_class_init (DBusGProxyClass *klass); static void dbus_gproxy_finalize (GObject *object); +static void dbus_gproxy_dispose (GObject *object); +static void dbus_gproxy_destroy (DBusGProxy *proxy); static void dbus_gproxy_emit_received (DBusGProxy *proxy, DBusMessage *message); @@ -174,6 +179,11 @@ dbus_gproxy_manager_unref (DBusGProxyManager *manager) if (manager->proxy_lists) { + /* can't have any proxies left since they hold + * a reference to the proxy manager. + */ + g_assert (g_hash_table_size (manager->proxy_lists) == 0); + g_hash_table_destroy (manager->proxy_lists); manager->proxy_lists = NULL; } @@ -447,11 +457,13 @@ dbus_gproxy_manager_unregister (DBusGProxyManager *manager, LOCK_MANAGER (manager); +#ifndef G_DISABLE_CHECKS if (manager->proxy_lists == NULL) { g_warning ("Trying to disconnect a signal on a proxy but none are connected\n"); return; } +#endif tri = tristring_from_proxy (proxy); @@ -459,21 +471,70 @@ dbus_gproxy_manager_unregister (DBusGProxyManager *manager, g_free (tri); +#ifndef G_DISABLE_CHECKS if (list == NULL) { g_warning ("Trying to disconnect a signal on a proxy but none are connected\n"); return; } +#endif g_assert (g_slist_find (list->proxies, proxy) != NULL); list->proxies = g_slist_remove (list->proxies, proxy); g_assert (g_slist_find (list->proxies, proxy) == NULL); + + if (g_hash_table_size (manager->proxy_lists) == 0) + { + g_hash_table_destroy (manager->proxy_lists); + manager->proxy_lists = NULL; + } UNLOCK_MANAGER (manager); } +static void +list_proxies_foreach (gpointer key, + gpointer value, + gpointer user_data) +{ + DBusGProxyList *list; + GSList **ret; + GSList *tmp; + + list = value; + ret = user_data; + + tmp = list->proxies; + while (tmp != NULL) + { + DBusGProxy *proxy = DBUS_GPROXY (tmp->data); + + g_object_ref (proxy); + *ret = g_slist_prepend (*ret, proxy); + + tmp = tmp->next; + } +} + +static GSList* +dbus_gproxy_manager_list_all (DBusGProxyManager *manager) +{ + GSList *ret; + + ret = NULL; + + if (manager->proxy_lists) + { + g_hash_table_foreach (manager->proxy_lists, + list_proxies_foreach, + &ret); + } + + return ret; +} + static DBusHandlerResult dbus_gproxy_manager_filter (DBusConnection *connection, DBusMessage *message, @@ -481,18 +542,48 @@ dbus_gproxy_manager_filter (DBusConnection *connection, { DBusGProxyManager *manager; - manager = user_data; - if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + manager = user_data; + + dbus_gproxy_manager_ref (manager); + + LOCK_MANAGER (manager); + if (dbus_message_is_signal (message, DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, "Disconnected")) { - /* FIXME g_object_run_dispose() all the proxies; should proxies have - * a "destroy" signal? + /* Destroy all the proxies, quite possibly resulting in unreferencing + * the proxy manager and the connection as well. */ + GSList *all; + GSList *tmp; + + all = dbus_gproxy_manager_list_all (manager); + + tmp = all; + while (tmp != NULL) + { + DBusGProxy *proxy; + + proxy = DBUS_GPROXY (tmp->data); + + UNLOCK_MANAGER (manager); + dbus_gproxy_destroy (proxy); + g_object_unref (G_OBJECT (proxy)); + LOCK_MANAGER (manager); + + tmp = tmp->next; + } + + g_slist_free (all); + +#ifndef G_DISABLE_CHECKS + if (manager->proxy_lists != NULL) + g_warning ("Disconnection emitted \"destroy\" on all DBusGProxy, but somehow new proxies were created in response to one of those destroy signals. This will cause a memory leak."); +#endif } else { @@ -507,14 +598,38 @@ dbus_gproxy_manager_filter (DBusConnection *connection, list = NULL; g_free (tri); + + /* Emit the signal */ if (list != NULL) { - /* FIXME Emit the signal on each proxy in the list */ - + GSList *tmp; + GSList *copy; + copy = g_slist_copy (list->proxies); + g_slist_foreach (copy, (GFunc) g_object_ref, NULL); + + tmp = copy; + while (tmp != NULL) + { + DBusGProxy *proxy; + + proxy = DBUS_GPROXY (tmp->data); + + UNLOCK_MANAGER (manager); + dbus_gproxy_emit_received (proxy, message); + g_object_unref (G_OBJECT (proxy)); + LOCK_MANAGER (manager); + + tmp = tmp->next; + } + + g_slist_free (copy); } } + + UNLOCK_MANAGER (manager); + dbus_gproxy_manager_unref (manager); /* "Handling" signals doesn't make sense, they are for everyone * who cares @@ -530,6 +645,7 @@ dbus_gproxy_manager_filter (DBusConnection *connection, enum { + DESTROY, RECEIVED, LAST_SIGNAL }; @@ -551,7 +667,17 @@ dbus_gproxy_class_init (DBusGProxyClass *klass) parent_class = g_type_class_peek_parent (klass); object_class->finalize = dbus_gproxy_finalize; - + object_class->dispose = dbus_gproxy_dispose; + + signals[DESTROY] = + g_signal_new ("destroy", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals[RECEIVED] = g_signal_new ("received", G_OBJECT_CLASS_TYPE (object_class), @@ -563,6 +689,19 @@ dbus_gproxy_class_init (DBusGProxyClass *klass) DBUS_TYPE_MESSAGE); } + +static void +dbus_gproxy_dispose (GObject *object) +{ + DBusGProxy *proxy; + + proxy = DBUS_GPROXY (object); + + g_signal_emit (object, signals[DESTROY], 0); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + static void dbus_gproxy_finalize (GObject *object) { @@ -583,6 +722,15 @@ dbus_gproxy_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static void +dbus_gproxy_destroy (DBusGProxy *proxy) +{ + /* FIXME do we need the GTK_IN_DESTRUCTION style flag + * from GtkObject? + */ + g_object_run_dispose (G_OBJECT (proxy)); +} + static char* create_signal_detail (const char *interface, const char *signal) @@ -697,18 +845,22 @@ dbus_gproxy_new (DBusConnection *connection, } /** - * Creates a new proxy for a remote interface. Method calls and signal - * connections over this proxy will go to the service owner; the - * service owner is expected to support the given interface name. THE - * SERVICE OWNER MAY CHANGE OVER TIME, for example between two - * different method calls. If you need a fixed owner, you need to - * request the current owner and bind a proxy to that rather than to - * the generic service name; see dbus_gproxy_new_for_service_owner(). + * Creates a new proxy for a remote interface exported by a service on + * a message bus. Method calls and signal connections over this proxy + * will go to the service owner; the service owner is expected to + * support the given interface name. THE SERVICE OWNER MAY CHANGE OVER + * TIME, for example between two different method calls. If you need a + * fixed owner, you need to request the current owner and bind a proxy + * to that rather than to the generic service name; see + * dbus_gproxy_new_for_service_owner(). * * A service-associated proxy only makes sense with a message bus, * not for app-to-app direct dbus connections. * - * @param connection the connection to the remote bus or app + * This proxy will only emit the "destroy" signal if the #DBusConnection + * is disconnected or the proxy is has no remaining references. + * + * @param connection the connection to the remote bus * @param service_name name of the service on the message bus * @param path_name name of the object inside the service to call methods on * @param interface_name name of the interface to call methods on @@ -733,6 +885,75 @@ dbus_gproxy_new_for_service (DBusConnection *connection, return proxy; } +/** + * Similar to dbus_gproxy_new_for_service(), but makes a round-trip + * request to the message bus to get the current service owner, then + * binds the proxy specifically to the current owner. As a result, the + * service owner will not change over time, and the proxy will emit + * the "destroy" signal when the owner disappears from the message + * bus. + * + * An example of the difference between dbus_gproxy_new_for_service() + * and dbus_gproxy_new_for_service_owner(): if you pass the service name + * "org.freedesktop.Database" dbus_gproxy_new_for_service() remains bound + * to that name as it changes owner. dbus_gproxy_new_for_service_owner() + * will fail if the service has no owner. If the service has an owner, + * dbus_gproxy_new_for_service_owner() will bind to the unique name + * of that owner rather than the generic service name. + * + * @param connection the connection to the remote bus + * @param service_name name of the service on the message bus + * @param path_name name of the object inside the service to call methods on + * @param interface_name name of the interface to call methods on + * @param error return location for an error + * @returns new proxy object, or #NULL on error + */ +DBusGProxy* +dbus_gproxy_new_for_service_owner (DBusConnection *connection, + const char *service_name, + const char *path_name, + const char *interface_name, + GError **error) +{ + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (service_name != NULL, NULL); + g_return_val_if_fail (path_name != NULL, NULL); + g_return_val_if_fail (interface_name != NULL, NULL); + + +} + +/** + * Creates a proxy for an object in peer application (one + * we're directly connected to). That is, this function is + * intended for use when there's no message bus involved, + * we're doing a simple 1-to-1 communication between two + * applications. + * + * + * @param connection the connection to the peer + * @param path_name name of the object inside the peer to call methods on + * @param interface_name name of the interface to call methods on + * @returns new proxy object + * + */ +DBusGProxy* +dbus_gproxy_new_for_peer (DBusConnection *connection, + const char *path_name, + const char *interface_name) +{ + DBusGProxy *proxy; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (path_name != NULL, NULL); + g_return_val_if_fail (interface_name != NULL, NULL); + + proxy = dbus_gproxy_new (connection, NULL, + path_name, interface_name); + + return proxy; +} + /** * Invokes a method on a remote interface. This function does not * block; instead it returns an opaque #DBusPendingCall object that @@ -952,7 +1173,7 @@ dbus_gproxy_connect_signal (DBusGProxy *proxy, const char *signal_name, DBusGProxySignalHandler handler, void *data, - GFreeFunc free_data_func) + GClosureNotify free_data_func) { GClosure *closure; char *detail; @@ -989,12 +1210,14 @@ dbus_gproxy_disconnect_signal (DBusGProxy *proxy, q = g_quark_try_string (detail); g_free (detail); +#ifndef G_DISABLE_CHECKS if (q == 0) { g_warning ("%s: No signal handlers for %s found on this DBusGProxy", G_GNUC_FUNCTION, signal_name); return; } +#endif g_signal_handlers_disconnect_matched (G_OBJECT (proxy), G_SIGNAL_MATCH_DETAIL | @@ -1018,7 +1241,8 @@ dbus_gproxy_disconnect_signal (DBusGProxy *proxy, dbus_bool_t _dbus_gproxy_test (void) { - + + return TRUE; } -- cgit