diff options
author | David Zeuthen <davidz@redhat.com> | 2010-05-05 15:14:22 -0400 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2010-05-05 15:14:22 -0400 |
commit | fa6c61da654a60df38234f6b07b28e7d189aab03 (patch) | |
tree | ec7b919caee33b40203363f5c3addf2e30027ed5 | |
parent | 5ac2a892e8be377d91d9ed9294a7781492860bf2 (diff) |
Add support for a G_DBUS_DEBUG environment variable
If 'authentication' is set we print output like in [0].
If 'messages' is set we print the output like in [1]. It would be cool
to resolve the inode to a file name but unfortunately there's no easy
way to do that...
[0] :
$ G_DBUS_DEBUG=authentication,message ./peer
/gdbus/peer-to-peer: GDBus-debug:Auth: CLIENT: initiating
GDBus-debug:Auth: SERVER: initiating
GDBus-debug:Auth: CLIENT: sent credentials
GDBus-debug:Auth: CLIENT: writing `AUTH\r\n'
GDBus-debug:Auth: CLIENT: WaitingForReject
GDBus-debug:Auth: SERVER: received credentials
GDBus-debug:Auth: SERVER: WaitingForAuth
GDBus-debug:Auth: SERVER: WaitingForAuth, read `AUTH'
GDBus-debug:Auth: SERVER: writing `REJECTED EXTERNAL DBUS_COOKIE_SHA1\r\n'
GDBus-debug:Auth: SERVER: WaitingForAuth
GDBus-debug:Auth: CLIENT: WaitingForReject, read 'REJECTED EXTERNAL DBUS_COOKIE_SHA1'
GDBus-debug:Auth: CLIENT: Trying to choose mechanism
GDBus-debug:Auth: CLIENT: Trying mechanism `EXTERNAL'
GDBus-debug:Auth: CLIENT: writing `AUTH EXTERNAL 353030\r\n'
GDBus-debug:Auth: CLIENT: WaitingForOK
GDBus-debug:Auth: SERVER: WaitingForAuth, read `AUTH EXTERNAL 353030'
GDBus-debug:Auth: SERVER: writing `OK aa7922555bd61069e1e083274be1c409\r\n'
GDBus-debug:Auth: SERVER: WaitingForBegin
GDBus-debug:Auth: CLIENT: WaitingForOK, read `OK aa7922555bd61069e1e083274be1c409'
GDBus-debug:Auth: CLIENT: writing `NEGOTIATE_UNIX_FD\r\n'
GDBus-debug:Auth: CLIENT: WaitingForAgreeUnixFD
GDBus-debug:Auth: SERVER: WaitingForBegin, read `NEGOTIATE_UNIX_FD'
GDBus-debug:Auth: SERVER: writing `AGREE_UNIX_FD\r\n'
GDBus-debug:Auth: SERVER: WaitingForBegin
GDBus-debug:Auth: CLIENT: WaitingForAgreeUnixFD, read=`AGREE_UNIX_FD'
GDBus-debug:Auth: CLIENT: writing `BEGIN\r\n'
GDBus-debug:Auth: CLIENT: Done, authenticated=1
GDBus-debug:Auth: SERVER: WaitingForBegin, read `BEGIN'
GDBus-debug:Auth: SERVER: Done, authenticated=1
[1] : This is also obtained from running the 'peer' test program
========================================================================
GDBus-debug:Message:
<<<< RECEIVED D-Bus message (143 bytes)
Type: method-call
Flags: none
Version: 0
Serial: 4
Headers:
path -> objectpath '/org/gtk/GDBus/PeerTestObject'
interface -> 'org.gtk.GDBus.PeerTestInterface'
member -> 'OpenFile'
signature -> signature 's'
Body: ('/etc/hosts',)
UNIX File Descriptors:
(none)
0000: 6c 01 00 01 0f 00 00 00 04 00 00 00 70 00 00 00 l...........p...
0010: 08 01 67 00 01 73 00 00 01 01 6f 00 1d 00 00 00 ..g..s....o.....
0020: 2f 6f 72 67 2f 67 74 6b 2f 47 44 42 75 73 2f 50 /org/gtk/GDBus/P
0030: 65 65 72 54 65 73 74 4f 62 6a 65 63 74 00 00 00 eerTestObject...
0040: 03 01 73 00 08 00 00 00 4f 70 65 6e 46 69 6c 65 ..s.....OpenFile
0050: 00 00 00 00 00 00 00 00 02 01 73 00 1f 00 00 00 ..........s.....
0060: 6f 72 67 2e 67 74 6b 2e 47 44 42 75 73 2e 50 65 org.gtk.GDBus.Pe
0070: 65 72 54 65 73 74 49 6e 74 65 72 66 61 63 65 00 erTestInterface.
0080: 0a 00 00 00 2f 65 74 63 2f 68 6f 73 74 73 00 ..../etc/hosts.
========================================================================
GDBus-debug:Message:
>>>> SENT D-Bus message (32 bytes)
Type: method-return
Flags: no-reply-expected
Version: 0
Serial: 0
Headers:
reply-serial -> uint32 4
num-unix-fds -> uint32 1
Body: ()
UNIX File Descriptors:
fd 21: dev=8:1,mode=0100644,ino=1171231,uid=0,gid=0,rdev=0:0,size=234,atime=1273070640,mtime=1267126160,ctime=1267126160
0000: 6c 02 01 01 00 00 00 00 05 00 00 00 10 00 00 00 l...............
0010: 09 01 75 00 01 00 00 00 05 01 75 00 04 00 00 00 ..u.......u.....
-rw-r--r-- | docs/reference/gdbus/gdbus-standalone-sections.txt | 1 | ||||
-rw-r--r-- | gdbus/gdbusauth.c | 42 | ||||
-rw-r--r-- | gdbus/gdbusauthmechanismsha1.c | 8 | ||||
-rw-r--r-- | gdbus/gdbusconnection.c | 5 | ||||
-rw-r--r-- | gdbus/gdbusmessage.c | 230 | ||||
-rw-r--r-- | gdbus/gdbusmessage.h | 2 | ||||
-rw-r--r-- | gdbus/gdbusprivate.c | 110 | ||||
-rw-r--r-- | gdbus/gdbusprivate.h | 2 |
8 files changed, 379 insertions, 21 deletions
diff --git a/docs/reference/gdbus/gdbus-standalone-sections.txt b/docs/reference/gdbus/gdbus-standalone-sections.txt index 053e737..1f3865e 100644 --- a/docs/reference/gdbus/gdbus-standalone-sections.txt +++ b/docs/reference/gdbus/gdbus-standalone-sections.txt @@ -127,6 +127,7 @@ g_dbus_message_new_method_call g_dbus_message_new_method_error g_dbus_message_new_method_reply g_dbus_message_new_signal +g_dbus_message_print g_dbus_message_get_type g_dbus_message_set_type g_dbus_message_get_serial diff --git a/gdbus/gdbusauth.c b/gdbus/gdbusauth.c index b5ccf42..9b4c1be 100644 --- a/gdbus/gdbusauth.c +++ b/gdbus/gdbusauth.c @@ -35,6 +35,7 @@ #include "gdbusutils.h" #include "gdbusenumtypes.h" #include "gcredentials.h" +#include "gdbusprivate.h" #ifdef G_OS_UNIX #include <gio/gunixconnection.h> @@ -49,28 +50,31 @@ static void debug_print (const gchar *message, ...) { #if DEBUG_ENABLED - gchar *s; - GString *str; - va_list var_args; - guint n; + if (G_UNLIKELY (_g_dbus_debug_authentication ())) + { + gchar *s; + GString *str; + va_list var_args; + guint n; - va_start (var_args, message); - s = g_strdup_vprintf (message, var_args); - va_end (var_args); + va_start (var_args, message); + s = g_strdup_vprintf (message, var_args); + va_end (var_args); - str = g_string_new (NULL); - for (n = 0; s[n] != '\0'; n++) - { - if (G_UNLIKELY (s[n] == '\r')) - g_string_append (str, "\\r"); - else if (G_UNLIKELY (s[n] == '\n')) - g_string_append (str, "\\n"); - else - g_string_append_c (str, s[n]); + str = g_string_new (NULL); + for (n = 0; s[n] != '\0'; n++) + { + if (G_UNLIKELY (s[n] == '\r')) + g_string_append (str, "\\r"); + else if (G_UNLIKELY (s[n] == '\n')) + g_string_append (str, "\\n"); + else + g_string_append_c (str, s[n]); + } + g_print ("GDBus-debug:Auth: %s\n", str->str); + g_string_free (str, TRUE); + g_free (s); } - g_print ("GDBusAuth-debug: %s\n", str->str); - g_string_free (str, TRUE); - g_free (s); #endif } diff --git a/gdbus/gdbusauthmechanismsha1.c b/gdbus/gdbusauthmechanismsha1.c index 5fca3ac..dcca119 100644 --- a/gdbus/gdbusauthmechanismsha1.c +++ b/gdbus/gdbusauthmechanismsha1.c @@ -445,6 +445,12 @@ keyring_lookup_entry (const gchar *cookie_context, } /* BOOH, didn't find the cookie */ + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_FAILED, + _("Didn't find cookie with id %d in the keyring at `%s'"), + cookie_id, + path); out: g_free (keyring_dir); @@ -1160,7 +1166,7 @@ mechanism_client_data_receive (GDBusAuthMechanism *mechanism, cookie = keyring_lookup_entry (cookie_context, cookie_id, &error); if (cookie == NULL) { - g_warning ("Problems lookup up entry in keyring: %s", error->message); + g_warning ("Problems looking up entry in keyring: %s", error->message); g_error_free (error); m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED; goto out; diff --git a/gdbus/gdbusconnection.c b/gdbus/gdbusconnection.c index bfa859f..2cfb923 100644 --- a/gdbus/gdbusconnection.c +++ b/gdbus/gdbusconnection.c @@ -975,7 +975,10 @@ g_dbus_connection_send_message_unlocked (GDBusConnection *connection, /* TODO: use connection->priv->auth to encode the blob */ if (out_serial != NULL) - *out_serial = serial_to_use; + { + *out_serial = serial_to_use; + g_dbus_message_set_serial (message, serial_to_use); + } _g_dbus_worker_send_message (connection->priv->worker, message, diff --git a/gdbus/gdbusmessage.c b/gdbus/gdbusmessage.c index 550aec5..e1f19bb 100644 --- a/gdbus/gdbusmessage.c +++ b/gdbus/gdbusmessage.c @@ -29,6 +29,14 @@ #include "gdbuserror.h" #include "gdbusenumtypes.h" +#ifdef G_OS_UNIX +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> +#endif + + /** * SECTION:gdbusmessage * @short_description: D-Bus Message @@ -2122,3 +2130,225 @@ g_dbus_message_to_gerror (GDBusMessage *message, } /* ---------------------------------------------------------------------------------------------------- */ + +static gchar * +enum_to_string (GType enum_type, gint value) +{ + gchar *ret; + GEnumClass *klass; + GEnumValue *enum_value; + + klass = g_type_class_ref (enum_type); + enum_value = g_enum_get_value (klass, value); + if (enum_value != NULL) + ret = g_strdup (enum_value->value_nick); + else + ret = g_strdup_printf ("unknown (value %d)", value); + g_type_class_unref (klass); + return ret; +} + +static gchar * +flags_to_string (GType flags_type, guint value) +{ + GString *s; + GFlagsClass *klass; + guint n; + + klass = g_type_class_ref (flags_type); + s = g_string_new (NULL); + for (n = 0; n < 32; n++) + { + if ((value & (1<<n)) != 0) + { + GFlagsValue *flags_value; + flags_value = g_flags_get_first_value (klass, (1<<n)); + if (s->len > 0) + g_string_append_c (s, ','); + if (flags_value != NULL) + g_string_append (s, flags_value->value_nick); + else + g_string_append_printf (s, "unknown (bit %d)", n); + } + } + if (s->len == 0) + g_string_append (s, "none"); + g_type_class_unref (klass); + return g_string_free (s, FALSE);; +} + +static gint +_sort_keys_func (gconstpointer a, + gconstpointer b) +{ + gint ia; + gint ib; + + ia = GPOINTER_TO_INT (a); + ib = GPOINTER_TO_INT (b); + + return ia - ib; +} + +/** + * g_dbus_message_print: + * @message: A #GDBusMessage. + * @indent: Indentation level. + * + * Produces a human-readable multi-line description of @message. + * + * The contents of the description has no ABI guarantees, the contents + * and formatting is subject to change at any time. Typical output + * looks something like this: + * <programlisting> + * Type: method-call + * Flags: none + * Version: 0 + * Serial: 4 + * Headers: + * path -> objectpath '/org/gtk/GDBus/TestObject' + * interface -> 'org.gtk.GDBus.TestInterface' + * member -> 'GimmeStdout' + * destination -> ':1.146' + * Body: () + * UNIX File Descriptors: + * (none) + * </programlisting> + * or + * <programlisting> + * Type: method-return + * Flags: no-reply-expected + * Version: 0 + * Serial: 477 + * Headers: + * reply-serial -> uint32 4 + * destination -> ':1.159' + * sender -> ':1.146' + * num-unix-fds -> uint32 1 + * Body: () + * UNIX File Descriptors: + * fd 12: dev=0:10,mode=020620,ino=5,uid=500,gid=5,rdev=136:2,size=0,atime=1273085037,mtime=1273085851,ctime=1272982635 + * </programlisting> + * + * Returns: A string that should be freed with g_free(). + */ +gchar * +g_dbus_message_print (GDBusMessage *message, + guint indent) +{ + GString *str; + gchar *s; + GList *keys; + GList *l; + + g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL); + + str = g_string_new (NULL); + + s = enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, message->priv->type); + g_string_append_printf (str, "%*sType: %s\n", indent, "", s); + g_free (s); + s = flags_to_string (G_TYPE_DBUS_MESSAGE_FLAGS, message->priv->flags); + g_string_append_printf (str, "%*sFlags: %s\n", indent, "", s); + g_free (s); + g_string_append_printf (str, "%*sVersion: %d\n", indent, "", message->priv->major_protocol_version); + g_string_append_printf (str, "%*sSerial: %d\n", indent, "", message->priv->serial); + + g_string_append_printf (str, "%*sHeaders:\n", indent, ""); + keys = g_hash_table_get_keys (message->priv->headers); + keys = g_list_sort (keys, _sort_keys_func); + if (keys != NULL) + { + for (l = keys; l != NULL; l = l->next) + { + gint key = GPOINTER_TO_INT (l->data); + GVariant *value; + gchar *value_str; + + value = g_hash_table_lookup (message->priv->headers, l->data); + g_assert (value != NULL); + + s = enum_to_string (G_TYPE_DBUS_MESSAGE_HEADER_FIELD, key); + value_str = g_variant_print (value, TRUE); + g_string_append_printf (str, "%*s %s -> %s\n", indent, "", s, value_str); + g_free (s); + g_free (value_str); + } + } + else + { + g_string_append_printf (str, "%*s (none)\n", indent, ""); + } + g_string_append_printf (str, "%*sBody: ", indent, ""); + if (message->priv->body != NULL) + { + g_variant_print_string (message->priv->body, + str, + TRUE); + } + else + { + g_string_append (str, "()"); + } + g_string_append (str, "\n"); +#ifdef G_OS_UNIX + g_string_append_printf (str, "%*sUNIX File Descriptors:\n", indent, ""); + if (message->priv->fd_list != NULL) + { + gint num_fds; + const gint *fds; + gint n; + + fds = g_unix_fd_list_peek_fds (message->priv->fd_list, &num_fds); + if (num_fds > 0) + { + for (n = 0; n < num_fds; n++) + { + GString *fs; + struct stat statbuf; + fs = g_string_new (NULL); + if (fstat (fds[n], &statbuf) == 0) + { + g_string_append_printf (fs, "%s" "dev=%d:%d", fs->len > 0 ? "," : "", + major (statbuf.st_dev), minor (statbuf.st_dev)); + g_string_append_printf (fs, "%s" "mode=0%o", fs->len > 0 ? "," : "", + statbuf.st_mode); + g_string_append_printf (fs, "%s" "ino=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "", + (guint64) statbuf.st_ino); + g_string_append_printf (fs, "%s" "uid=%d", fs->len > 0 ? "," : "", + statbuf.st_uid); + g_string_append_printf (fs, "%s" "gid=%d", fs->len > 0 ? "," : "", + statbuf.st_gid); + g_string_append_printf (fs, "%s" "rdev=%d:%d", fs->len > 0 ? "," : "", + major (statbuf.st_rdev), minor (statbuf.st_rdev)); + g_string_append_printf (fs, "%s" "size=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "", + (guint64) statbuf.st_size); + g_string_append_printf (fs, "%s" "atime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "", + (guint64) statbuf.st_atime); + g_string_append_printf (fs, "%s" "mtime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "", + (guint64) statbuf.st_mtime); + g_string_append_printf (fs, "%s" "ctime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "", + (guint64) statbuf.st_ctime); + } + else + { + g_string_append_printf (fs, "(fstat failed: %s)", strerror (errno)); + } + g_string_append_printf (str, "%*s fd %d: %s\n", indent, "", fds[n], fs->str); + g_string_free (fs, TRUE); + } + } + else + { + g_string_append_printf (str, "%*s (empty)\n", indent, ""); + } + } + else + { + g_string_append_printf (str, "%*s (none)\n", indent, ""); + } +#endif + + return g_string_free (str, FALSE); +} + diff --git a/gdbus/gdbusmessage.h b/gdbus/gdbusmessage.h index 7a565b3..224f66f 100644 --- a/gdbus/gdbusmessage.h +++ b/gdbus/gdbusmessage.h @@ -82,6 +82,8 @@ GDBusMessage *g_dbus_message_new_method_reply (GDBusMessage GDBusMessage *g_dbus_message_new_method_error (GDBusMessage *method_call_message, const gchar *error_name, const gchar *error_message); +gchar *g_dbus_message_print (GDBusMessage *message, + guint indent); GDBusMessageType g_dbus_message_get_type (GDBusMessage *message); void g_dbus_message_set_type (GDBusMessage *message, diff --git a/gdbus/gdbusprivate.c b/gdbus/gdbusprivate.c index 34f3f79..f28abbb 100644 --- a/gdbus/gdbusprivate.c +++ b/gdbus/gdbusprivate.c @@ -41,6 +41,41 @@ /* ---------------------------------------------------------------------------------------------------- */ +static gchar * +hexdump (const gchar *data, gsize len, guint indent) +{ + guint n, m; + GString *ret; + + ret = g_string_new (NULL); + + for (n = 0; n < len; n += 16) + { + g_string_append_printf (ret, "%*s%04x: ", indent, "", n); + + for (m = n; m < n + 16; m++) + { + if (m > n && (m%4) == 0) + g_string_append_c (ret, ' '); + if (m < len) + g_string_append_printf (ret, "%02x ", (gint) data[m]); + else + g_string_append (ret, " "); + } + + g_string_append (ret, " "); + + for (m = n; m < len && m < n + 16; m++) + g_string_append_c (ret, g_ascii_isprint ((gint) data[m]) ? (gint) data[m] : '.'); + + g_string_append_c (ret, '\n'); + } + + return g_string_free (ret, FALSE); +} + +/* ---------------------------------------------------------------------------------------------------- */ + /* Unfortunately ancillary messages are discarded when reading from a * socket using the GSocketInputStream abstraction. So we provide a * very GInputStream-ish API that uses GSocket in this case (very @@ -548,6 +583,21 @@ _g_dbus_worker_do_read_cb (GInputStream *input_stream, worker->read_fd_list = NULL; } + if (G_UNLIKELY (_g_dbus_debug_message ())) + { + gchar *s; + g_print ("========================================================================\n" + "GDBus-debug:Message:\n" + " <<<< RECEIVED D-Bus message (%" G_GSIZE_FORMAT " bytes)\n", + worker->read_buffer_cur_size); + s = g_dbus_message_print (message, 2); + g_print ("%s", s); + g_free (s); + s = hexdump (worker->read_buffer, worker->read_buffer_cur_size, 2); + g_print ("%s\n", s); + g_free (s); + } + /* yay, got a message, go deliver it */ _g_dbus_worker_emit_message (worker, message); g_object_unref (message); @@ -742,6 +792,21 @@ write_message (GDBusWorker *worker, ret = TRUE; + if (G_UNLIKELY (_g_dbus_debug_message ())) + { + gchar *s; + g_print ("========================================================================\n" + "GDBus-debug:Message:\n" + " >>>> SENT D-Bus message (%" G_GSIZE_FORMAT " bytes)\n", + data->blob_size); + s = g_dbus_message_print (data->message, 2); + g_print ("%s", s); + g_free (s); + s = hexdump (data->blob, data->blob_size, 2); + g_print ("%s\n", s); + g_free (s); + } + out: return ret; } @@ -889,6 +954,32 @@ _g_dbus_worker_stop (GDBusWorker *worker) _g_dbus_worker_unref (worker); } +#define G_DBUS_DEBUG_AUTHENTICATON (1<<0) +#define G_DBUS_DEBUG_MESSAGE (1<<1) +static gint _gdbus_debug_flags = 0; + +gboolean +_g_dbus_debug_authentication (void) +{ + _g_dbus_initialize (); + return (_gdbus_debug_flags & G_DBUS_DEBUG_AUTHENTICATON) != 0; +} + +gboolean +_g_dbus_debug_message (void) +{ + _g_dbus_initialize (); + return (_gdbus_debug_flags & G_DBUS_DEBUG_MESSAGE) != 0; +} + +/** + * _g_dbus_initialize: + * + * Does various one-time init things such as + * + * - registering the G_DBUS_ERROR error domain + * - parses the G_DBUS_DEBUG environment variable + */ void _g_dbus_initialize (void) { @@ -897,7 +988,26 @@ _g_dbus_initialize (void) if (g_once_init_enter (&initialized)) { volatile GQuark g_dbus_error_domain; + const gchar *debug; + g_dbus_error_domain = G_DBUS_ERROR; + + debug = g_getenv ("G_DBUS_DEBUG"); + if (debug != NULL) + { + gchar **tokens; + guint n; + tokens = g_strsplit (debug, ",", 0); + for (n = 0; tokens[n] != NULL; n++) + { + if (g_strcmp0 (tokens[n], "authentication") == 0) + _gdbus_debug_flags |= G_DBUS_DEBUG_AUTHENTICATON; + else if (g_strcmp0 (tokens[n], "message") == 0) + _gdbus_debug_flags |= G_DBUS_DEBUG_MESSAGE; + } + g_strfreev (tokens); + } + g_once_init_leave (&initialized, 1); } } diff --git a/gdbus/gdbusprivate.h b/gdbus/gdbusprivate.h index becad23..8d59c1a 100644 --- a/gdbus/gdbusprivate.h +++ b/gdbus/gdbusprivate.h @@ -65,6 +65,8 @@ void _g_dbus_worker_stop (GDBusWorker *worker); /* ---------------------------------------------------------------------------------------------------- */ void _g_dbus_initialize (void); +gboolean _g_dbus_debug_authentication (void); +gboolean _g_dbus_debug_message (void); gboolean _g_dbus_address_parse_entry (const gchar *address_entry, gchar **out_transport_name, |