[GnomeMeeting-devel-list] [PATCH] leaks in the dbus component
- From: PUYDT Julien <jpuydt free fr>
- To: GnomeMeeting Devel Liste <gnomemeeting-devel-list gnome org>
- Subject: [GnomeMeeting-devel-list] [PATCH] leaks in the dbus component
- Date: Mon, 20 Dec 2004 19:41:08 +0100
Hi,
the following patch fixes leaks in the dbus component.
It also renames the names of the dbus service&object&interface to
something better (at least imnsho). The attached gm_remote.c is updated
to reflect this.
I don't want to apply that patch myself, since I don't want to do
anything that would disturb Damien's work (well, that and the fact that
committing on a 56k is really painful).
Snark
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus.h>
#include <dbus/dbus-glib-lowlevel.h>
#define SERVICE "org.gnomemeeting.instance"
#define INTERFACE "org.gnomemeeting.instance"
#define OBJECT "/org/gnomemeeting/instance"
struct needed_data {
DBusConnection *connection;
GtkWidget *window;
GtkListStore *call_store;
GtkTreeView *call_view;
};
enum {
CALL_TOKEN_COLUMN,
NAME_COLUMN,
URL_COLUMN,
APP_COLUMN,
NUMBER_OF_COLUMNS
};
/* various helpers (declaration) */
static GtkWidget *call_popup_new (const struct needed_data *my_data);
static gboolean set_iter_on_right_call_token (GtkTreeModel *model,
GtkTreeIter *iter,
gchar *call_token);
static void add_call (struct needed_data *my_data,
gchar *call_token);
static void delete_call (struct needed_data *my_data,
gchar *call_token);
/* gtk callbacks (declaration) */
static gint call_clicked_cb (GtkWidget *widget,
GdkEventButton *button,
gpointer user_data);
static void connect_cb (GtkWidget *,
gpointer);
static void disconnect_cb (GtkWidget *,
gpointer);
static void launch_cb (GtkWidget *,
gpointer);
/* DBUS helpers (declaration) */
static DBusHandlerResult filter_func (DBusConnection *connection,
DBusMessage *message,
void *user_data);
/* various helpers (implementation) */
static GtkWidget *
call_popup_new (const struct needed_data *my_data)
{
GtkWidget *popup = NULL;
GtkWidget *item = NULL;
popup = gtk_menu_new ();
item = gtk_menu_item_new_with_label ("Disconnect");
g_signal_connect (G_OBJECT (item), "activate",
GTK_SIGNAL_FUNC (disconnect_cb), (gpointer)my_data);
gtk_menu_append (popup, item);
return popup;
}
static gboolean
set_iter_on_right_call_token (GtkTreeModel *model,
GtkTreeIter *iter,
gchar *call_token)
{
gchar *iter_call_token = NULL;
g_return_val_if_fail (model != NULL
&& iter != NULL
&& call_token != NULL, FALSE);
if (gtk_tree_model_get_iter_first (model, iter)) {
do {
gtk_tree_model_get (model, iter,
CALL_TOKEN_COLUMN, &iter_call_token,
-1);
if (strcmp (call_token, iter_call_token) == 0)
return TRUE;
} while (gtk_tree_model_iter_next (model, iter));
}
return FALSE;
}
static void
add_call (struct needed_data *my_data,
gchar *call_token)
{
gchar *name = NULL;
gchar *url = NULL;
gchar *app = NULL;
GtkTreeIter iter;
DBusMessage *message = NULL;
DBusMessage *reply = NULL;
DBusPendingCall *call = NULL;
DBusError error;
g_return_if_fail (my_data != NULL && call_token != NULL);
g_print ("add call %s\n", call_token);
dbus_error_init (&error);
/* first, get the data */
message = dbus_message_new_method_call (SERVICE, OBJECT,
INTERFACE, "GetCallInfo");
(void)dbus_message_append_args (message,
DBUS_TYPE_STRING, call_token,
DBUS_TYPE_INVALID);
dbus_message_set_no_reply (message, FALSE);
(void)dbus_connection_send_with_reply (my_data->connection, message,
&call, -1);
dbus_connection_flush (my_data->connection);
dbus_pending_call_block (call);
reply = dbus_pending_call_get_reply (call);
if (!dbus_message_get_args (reply, NULL,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_STRING, &url,
DBUS_TYPE_STRING, &app,
DBUS_TYPE_INVALID)) {
g_print ("Couldn't get name, url & app: %s\n", name);
dbus_error_free (&error);
return;
}
/* then push it in the store */
gtk_list_store_append (my_data->call_store, &iter);
gtk_list_store_set (my_data->call_store, &iter,
CALL_TOKEN_COLUMN, call_token,
NAME_COLUMN, name,
URL_COLUMN, url,
APP_COLUMN, app,
-1);
}
static void
delete_call (struct needed_data *my_data,
gchar *call_token)
{
GtkTreeIter iter;
g_print ("delete_call %s\n", call_token);
g_return_if_fail (my_data != NULL && call_token != NULL);
if (set_iter_on_right_call_token (GTK_TREE_MODEL (my_data->call_store),
&iter, call_token)) {
(void)gtk_list_store_remove (my_data->call_store, &iter);
}
}
static void
update_status (struct needed_data *my_data)
{
DBusMessage *message = NULL;
DBusMessage *reply = NULL;
DBusPendingCall *call = NULL;
gchar *title = NULL;
g_print ("update_status\n");
if (dbus_bus_service_exists (my_data->connection, SERVICE, NULL)) {
message = dbus_message_new_method_call (SERVICE, OBJECT,
INTERFACE, "GetState");
dbus_message_set_no_reply (message, FALSE);
(void)dbus_connection_send_with_reply (my_data->connection, message,
&call, -1);
dbus_connection_flush (my_data->connection);
dbus_pending_call_block (call);
reply = dbus_pending_call_get_reply (call);
if (dbus_message_get_args (reply, NULL,
DBUS_TYPE_STRING, &title,
DBUS_TYPE_INVALID)) {
gtk_window_set_title (GTK_WINDOW (my_data->window), title);
g_free (title);
}
dbus_message_unref (message);
dbus_message_unref (reply);
dbus_pending_call_unref (call);
}
else
gtk_window_set_title (GTK_WINDOW (my_data->window), "Not running");
}
/* gtk callbacks (implementation) */
static gint
call_clicked_cb (GtkWidget *widget,
GdkEventButton *button,
gpointer user_data)
{
struct needed_data *my_data = (struct needed_data *)user_data;
GtkWidget *popup = NULL;
if (button->type == GDK_BUTTON_PRESS && button->button == 3) {
popup = call_popup_new (my_data);
gtk_menu_popup (GTK_MENU (popup), NULL, NULL, NULL, NULL,
button->button, button->time);
g_signal_connect (G_OBJECT (popup), "hide",
GTK_SIGNAL_FUNC (g_object_unref), (gpointer)popup);
g_object_ref (G_OBJECT (popup)); /* gtk memory management */
gtk_object_sink (GTK_OBJECT (popup)); /* is amazing */
gtk_widget_show_all (popup);
}
return TRUE;
}
static void
connect_cb (GtkWidget *widget,
gpointer user_data)
{
struct needed_data *my_data = (struct needed_data *)user_data;
DBusMessage *message = NULL;
message = dbus_message_new_method_call (SERVICE, OBJECT,
INTERFACE, "ConnectTo");
(void)dbus_message_append_args (message,
DBUS_TYPE_STRING,
gtk_entry_get_text (GTK_ENTRY (widget)),
DBUS_TYPE_INVALID);
dbus_message_set_no_reply (message, TRUE);
(void)dbus_connection_send (my_data->connection, message, NULL);
dbus_connection_flush (my_data->connection);
dbus_message_unref (message);
}
static void
disconnect_cb (GtkWidget *widget,
gpointer user_data)
{
struct needed_data *my_data = (struct needed_data *)user_data;
GtkTreeSelection *selection = NULL;
GtkTreeIter iter;
gchar *call_token = NULL;
DBusMessage *message = NULL;
selection = gtk_tree_view_get_selection (my_data->call_view);
if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
gtk_tree_model_get (GTK_TREE_MODEL (my_data->call_store), &iter,
CALL_TOKEN_COLUMN, &call_token,
-1);
message = dbus_message_new_method_call (SERVICE, OBJECT,
INTERFACE, "Disconnect");
(void)dbus_message_append_args (message,
DBUS_TYPE_STRING, call_token,
DBUS_TYPE_INVALID);
dbus_message_set_no_reply (message, TRUE);
(void)dbus_connection_send (my_data->connection, message, NULL);
dbus_connection_flush (my_data->connection);
dbus_message_unref (message);
}
}
static void
launch_cb (GtkWidget *widget,
gpointer user_data)
{
struct needed_data *my_data = (struct needed_data *)user_data;
(void)dbus_bus_activate_service (my_data->connection, SERVICE, 0, NULL, NULL);
}
/* DBUS helpers (implementation) */
static DBusHandlerResult
filter_func(DBusConnection *connection,
DBusMessage *message,
void *user_data)
{
struct needed_data *my_data = (struct needed_data *)user_data;
char *str = NULL;
/* we just lost contact with DBUS */
if (dbus_message_is_signal (message,
DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
"Disconnected"))
{
g_print ("Disconnected\n");
exit (-1); /* just die */
return DBUS_HANDLER_RESULT_HANDLED;
}
/* DBUS says someone got/lost a service */
else if (dbus_message_is_signal (message,
DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
"ServiceCreated")
|| dbus_message_is_signal (message,
DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
"ServiceDeleted")) {
dbus_message_get_args (message,
NULL,
DBUS_TYPE_STRING, &str,
DBUS_TYPE_INVALID);
if (strcmp (str, SERVICE) == 0) { /* check it's the right service */
update_status (my_data);
return DBUS_HANDLER_RESULT_HANDLED;
}
}
/* the rest of the messages are from gnomemeeting itself */
else if (dbus_message_is_signal (message,
INTERFACE,
"StateChanged")) {
update_status (my_data);
}
else if (dbus_message_is_signal (message,
INTERFACE,
"AddCall")) {
dbus_message_get_args (message,
NULL,
DBUS_TYPE_STRING, &str,
DBUS_TYPE_INVALID);
add_call (my_data, str);
}
else if (dbus_message_is_signal (message,
INTERFACE,
"DeleteCall")) {
dbus_message_get_args (message,
NULL,
DBUS_TYPE_STRING, &str,
DBUS_TYPE_INVALID);
delete_call (my_data, str);
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
/* well... */
int main (int argc,
char *argv [])
{
GtkWidget *window = NULL;
GtkListStore *call_store = NULL;
GtkWidget *call_view = NULL;
GtkCellRenderer *renderer = NULL;
GtkTreeViewColumn *column = NULL;
GtkWidget *vbox = NULL;
GtkWidget *hbox = NULL;
GtkWidget *entry = NULL;
GtkWidget *entry_label = NULL;
GtkWidget *launch_button = NULL;
struct needed_data *my_data = NULL;
gtk_set_locale ();
gtk_init (&argc, &argv);
my_data = g_new0 (struct needed_data, 1);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
my_data->window = window;
g_signal_connect (G_OBJECT (window), "delete-event",
G_CALLBACK (gtk_false), NULL);
g_signal_connect (G_OBJECT (window), "destroy",
G_CALLBACK (gtk_main_quit), NULL);
vbox = gtk_vbox_new (FALSE, 2);
gtk_container_add (GTK_CONTAINER (window), vbox);
call_store = gtk_list_store_new (NUMBER_OF_COLUMNS,
G_TYPE_STRING, /* call token */
G_TYPE_STRING, /* name */
G_TYPE_STRING, /* url */
G_TYPE_STRING); /* app */
my_data->call_store = call_store;
call_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (call_store));
my_data->call_view = GTK_TREE_VIEW (call_view);
gtk_box_pack_start (GTK_BOX (vbox), call_view, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (call_view), "event-after",
G_CALLBACK (call_clicked_cb), my_data);
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Name",
renderer,
"text", NAME_COLUMN,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (call_view), column);
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("URL",
renderer,
"text", URL_COLUMN,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (call_view), column);
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Application",
renderer,
"text", APP_COLUMN,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (call_view), column);
/* test line */
GtkTreeIter iter;
gtk_list_store_append (call_store, &iter);
gtk_list_store_set (call_store, &iter,
CALL_TOKEN_COLUMN, "test",
NAME_COLUMN, "Remote user",
URL_COLUMN, "In a galaxy far far away",
APP_COLUMN, "Gnomemeeting II",
-1);
/* end test */
hbox = gtk_hbox_new (FALSE, 6);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
entry_label = gtk_label_new ("URL: ");
gtk_box_pack_start (GTK_BOX (hbox), entry_label, FALSE, FALSE, 0);
entry = gtk_entry_new ();
gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (entry), "activate",
GTK_SIGNAL_FUNC (connect_cb), (gpointer)my_data);
launch_button = gtk_button_new_with_label ("Launch GM");
g_signal_connect (G_OBJECT (launch_button), "clicked",
GTK_SIGNAL_FUNC (launch_cb), (gpointer)my_data);
gtk_box_pack_start (GTK_BOX (hbox), launch_button, FALSE, FALSE, 0);
gtk_widget_show_all (window);
my_data->connection = dbus_bus_get (DBUS_BUS_SESSION, NULL);
/* tell DBUS where our ears are */
if (!dbus_connection_add_filter (my_data->connection,
filter_func,
my_data, NULL)) {
g_print ("Couldn't add filter\n");
exit (-1);
}
/* DBUS will tell us when gnomemeeting comes and goes */
dbus_bus_add_match (my_data->connection,
"type='signal',"
"sender='" DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS "',"
"interface='" DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS "'",
NULL);
/* we want to know what gnomemeeting signals */
dbus_bus_add_match (my_data->connection,
"type='signal',"
"interface='" INTERFACE "'",
NULL);
update_status (my_data);
dbus_connection_setup_with_g_main (my_data->connection, NULL);
gtk_main ();
return 0;
}
diff -ur gnomemeeting/gnomemeeting.service.in gnomemeeting.patched/gnomemeeting.service.in
--- gnomemeeting/gnomemeeting.service.in 2004-10-27 09:52:45 +0200
+++ gnomemeeting.patched/gnomemeeting.service.in 2004-12-20 15:51:18 +0100
@@ -1,4 +1,4 @@
[D-BUS Service]
-Name=org.gnomemeeting.CallService
+Name=org.gnomemeeting.instance
Exec= prefix@/bin/gnomemeeting
diff -ur gnomemeeting/src/dbus_component.cpp gnomemeeting.patched/src/dbus_component.cpp
--- gnomemeeting/src/dbus_component.cpp 2004-10-27 09:52:45 +0200
+++ gnomemeeting.patched/src/dbus_component.cpp 2004-12-20 15:51:02 +0100
@@ -542,6 +542,7 @@
DBUS_TYPE_INVALID)) {
GnomeMeeting::Process ()->Connect (address);
+ g_free (address);
}
}
@@ -580,6 +581,7 @@
/* FIXME: should use call_token, when gnomemeeting will support it! */
GnomeMeeting::Process ()->Disconnect ();
+ g_free (call_token);
}
}
@@ -642,6 +644,9 @@
dbus_connection_flush (connection);
}
dbus_message_unref (reply);
+ g_free (name);
+ g_free (app);
+ g_free (url);
}
}
@@ -676,7 +681,7 @@
void
dbus_component_call_address (GObject *object,
- gchar *address)
+ const gchar *address)
{
DBusMessage *message = NULL;
DBusComponent *self = NULL;
diff -ur gnomemeeting/src/dbus_component.h gnomemeeting.patched/src/dbus_component.h
--- gnomemeeting/src/dbus_component.h 2004-10-27 09:52:45 +0200
+++ gnomemeeting.patched/src/dbus_component.h 2004-12-20 15:51:02 +0100
@@ -111,9 +111,9 @@
* "endpoint-state-changed".
*/
-#define GM_DBUS_OBJECT_PATH "/org/gnomemeeting/Endpoint"
-#define GM_DBUS_INTERFACE "org.gnomemeeting.CallService"
-#define GM_DBUS_SERVICE "org.gnomemeeting.CallService"
+#define GM_DBUS_SERVICE "org.gnomemeeting.instance"
+#define GM_DBUS_INTERFACE "org.gnomemeeting.instance"
+#define GM_DBUS_OBJECT_PATH "/org/gnomemeeting/instance"
G_BEGIN_DECLS
@@ -144,7 +144,7 @@
* url.
* PRE : A non-NULL DBUS component casted as a GObject, and an URL
*/
-void dbus_component_call_address (GObject *object, gchar *url);
+void dbus_component_call_address (GObject *object, const gchar *url);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]