summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Thompson <will.thompson@collabora.co.uk>2011-06-22 14:33:52 +0100
committerWill Thompson <will.thompson@collabora.co.uk>2011-11-18 10:43:05 +0000
commit33f739934f7a8f01aaec71400afd584be24d4e72 (patch)
tree46c7a49165d599e1fd4b9093bdd816743f79b75c
parentc48ab1e75a698bda268a4331ed4d793af98ae3b8 (diff)
Add an XMPP console sidecar
It currently only supports sending an arbitrary IQ and getting the reply. Obviously this is for developer use only.
-rw-r--r--gabble/extensions/Gabble_Plugin_Console.xml66
-rw-r--r--gabble/extensions/Makefile.am1
-rw-r--r--gabble/extensions/all.xml1
-rw-r--r--gabble/plugins/Makefile.am5
-rw-r--r--gabble/plugins/console.c430
-rw-r--r--gabble/plugins/console.h85
6 files changed, 588 insertions, 0 deletions
diff --git a/gabble/extensions/Gabble_Plugin_Console.xml b/gabble/extensions/Gabble_Plugin_Console.xml
new file mode 100644
index 000000000..f00a24ad3
--- /dev/null
+++ b/gabble/extensions/Gabble_Plugin_Console.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" ?>
+<node name="/Gabble_Plugin_Console"
+ xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
+ <tp:copyright>Copyright © 2011 Collabora Ltd.</tp:copyright>
+ <tp:license xmlns="http://www.w3.org/1999/xhtml">
+ <p>This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.</p>
+
+ <p>This library 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
+ Lesser General Public License for more details.</p>
+
+ <p>You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA.</p>
+ </tp:license>
+
+ <interface name="org.freedesktop.Telepathy.Gabble.Plugin.Console">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>A sidecar interface providing an XMPP console.</p>
+ </tp:docstring>
+
+ <method name="SendIQ" tp:name-for-bindings="Send_IQ">
+ <arg direction="in" name="Type" type="s">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ The type of IQ request to send; either <code>"get"</code> or
+ <code>"set"</code>.
+ </tp:docstring>
+ </arg>
+ <arg direction="in" name="To" type="s">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ The recipient for the IQ; or the empty string to send an IQ to the
+ server (with no recipient specified).
+ </tp:docstring>
+ </arg>
+ <arg direction="in" name="Body" type="s">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ An XML fragment for the body of the IQ, which MUST have exactly one
+ top-level element.
+ </tp:docstring>
+ </arg>
+ <arg direction="out" name="Reply_Type" type="s">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ The type of IQ reply; either <code>"result"</code> or
+ <code>"error"</code>.
+ </tp:docstring>
+ </arg>
+ <arg direction="out" name="Body" type="s">
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ An XML fragment for the body of the response, which MUST have between
+ zero and two top-level elements (the query element, an error element,
+ both, or neither).
+ </tp:docstring>
+ </arg>
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ Hai.
+ </tp:docstring>
+ </method>
+
+ </interface>
+</node>
+<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/gabble/extensions/Makefile.am b/gabble/extensions/Makefile.am
index feee4e790..10cab4308 100644
--- a/gabble/extensions/Makefile.am
+++ b/gabble/extensions/Makefile.am
@@ -5,6 +5,7 @@ EXTRA_DIST = \
Channel_Type_FileTransfer_Future.xml \
Connection_Future.xml \
Connection_Interface_Gabble_Decloak.xml \
+ Gabble_Plugin_Console.xml \
Gabble_Plugin_Gateways.xml \
Gabble_Plugin_Test.xml \
OLPC_Activity_Properties.xml \
diff --git a/gabble/extensions/all.xml b/gabble/extensions/all.xml
index cb368ef9e..90f52a89b 100644
--- a/gabble/extensions/all.xml
+++ b/gabble/extensions/all.xml
@@ -40,6 +40,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA</p>
<xi:include href="Connection_Interface_Gabble_Decloak.xml"/>
<xi:include href="Connection_Future.xml"/>
+<xi:include href="Gabble_Plugin_Console.xml"/>
<xi:include href="Gabble_Plugin_Gateways.xml"/>
<xi:include href="Gabble_Plugin_Test.xml"/>
diff --git a/gabble/plugins/Makefile.am b/gabble/plugins/Makefile.am
index 97f87a4c5..5d4715be1 100644
--- a/gabble/plugins/Makefile.am
+++ b/gabble/plugins/Makefile.am
@@ -1,6 +1,7 @@
plugindir = $(libdir)/telepathy/gabble-0
installable_plugins = \
+ console.la \
gateways.la
test_only_plugins = \
@@ -45,6 +46,10 @@ gateways_la_SOURCES = \
gateways.c \
gateways.h
+console_la_SOURCES = \
+ console.c \
+ console.h
+
AM_CFLAGS = $(ERROR_CFLAGS) \
-I $(top_srcdir) -I $(top_builddir) \
@DBUS_CFLAGS@ @GLIB_CFLAGS@ @WOCKY_CFLAGS@ @TP_GLIB_CFLAGS@ \
diff --git a/gabble/plugins/console.c b/gabble/plugins/console.c
new file mode 100644
index 000000000..47375f774
--- /dev/null
+++ b/gabble/plugins/console.c
@@ -0,0 +1,430 @@
+/* XML console plugin
+ *
+ * Copyright © 2011 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "console.h"
+
+#include "config.h"
+
+#include <string.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+
+#include <wocky/wocky-xmpp-error.h>
+#include <wocky/wocky-utils.h>
+#include <wocky/wocky-xmpp-reader.h>
+#include <wocky/wocky-xmpp-writer.h>
+
+#include "extensions/extensions.h"
+
+#include <gabble/gabble.h>
+
+/*************************
+ * Plugin implementation *
+ *************************/
+
+static guint debug = 0;
+
+#define DEBUG(format, ...) \
+G_STMT_START { \
+ if (debug != 0) \
+ g_debug ("%s: " format, G_STRFUNC, ## __VA_ARGS__); \
+} G_STMT_END
+
+static const GDebugKey debug_keys[] = {
+ { "console", 1 },
+ { NULL, 0 }
+};
+
+static void plugin_iface_init (
+ gpointer g_iface,
+ gpointer data);
+
+static const gchar * const sidecar_interfaces[] = {
+ GABBLE_IFACE_GABBLE_PLUGIN_CONSOLE,
+ NULL
+};
+
+G_DEFINE_TYPE_WITH_CODE (GabbleConsolePlugin, gabble_console_plugin,
+ G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GABBLE_TYPE_PLUGIN, plugin_iface_init);
+ )
+
+static void
+gabble_console_plugin_init (GabbleConsolePlugin *self)
+{
+}
+
+static void
+gabble_console_plugin_class_init (GabbleConsolePluginClass *klass)
+{
+}
+
+static void
+gabble_console_plugin_create_sidecar (
+ GabblePlugin *plugin,
+ const gchar *sidecar_interface,
+ GabbleConnection *connection,
+ WockySession *session,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (plugin),
+ callback, user_data,
+ /* sic: all plugins share gabble_plugin_create_sidecar_finish() so we
+ * need to use the same source tag.
+ */
+ gabble_plugin_create_sidecar);
+ GabbleSidecar *sidecar = NULL;
+
+ if (!tp_strdiff (sidecar_interface, GABBLE_IFACE_GABBLE_PLUGIN_CONSOLE))
+ {
+ sidecar = g_object_new (GABBLE_TYPE_CONSOLE_SIDECAR,
+ "connection", connection,
+ "session", session,
+ NULL);
+ }
+ else
+ {
+ g_simple_async_result_set_error (result, TP_ERRORS,
+ TP_ERROR_NOT_IMPLEMENTED, "'%s' not implemented", sidecar_interface);
+ }
+
+ if (sidecar != NULL)
+ g_simple_async_result_set_op_res_gpointer (result, sidecar,
+ g_object_unref);
+
+ g_simple_async_result_complete_in_idle (result);
+ g_object_unref (result);
+}
+
+static void
+plugin_iface_init (
+ gpointer g_iface,
+ gpointer data G_GNUC_UNUSED)
+{
+ GabblePluginInterface *iface = g_iface;
+
+ iface->name = "XMPP console";
+ iface->version = PACKAGE_VERSION;
+ iface->sidecar_interfaces = sidecar_interfaces;
+ iface->create_sidecar = gabble_console_plugin_create_sidecar;
+}
+
+GabblePlugin *
+gabble_plugin_create (void)
+{
+ debug = g_parse_debug_string (g_getenv ("GABBLE_DEBUG"), debug_keys,
+ G_N_ELEMENTS (debug_keys) - 1);
+ DEBUG ("loaded");
+
+ return g_object_new (GABBLE_TYPE_CONSOLE_PLUGIN,
+ NULL);
+}
+
+/**************************
+ * Sidecar implementation *
+ **************************/
+
+enum {
+ PROP_0,
+ PROP_CONNECTION,
+ PROP_SESSION
+};
+
+struct _GabbleConsoleSidecarPrivate
+{
+ WockySession *session;
+ TpBaseConnection *connection;
+ WockyXmppReader *reader;
+ WockyXmppWriter *writer;
+};
+
+static void sidecar_iface_init (
+ gpointer g_iface,
+ gpointer data);
+
+static void console_iface_init (
+ gpointer g_iface,
+ gpointer data);
+
+G_DEFINE_TYPE_WITH_CODE (GabbleConsoleSidecar, gabble_console_sidecar,
+ G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SIDECAR, sidecar_iface_init);
+ G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_GABBLE_PLUGIN_CONSOLE,
+ console_iface_init);
+ )
+
+static void
+gabble_console_sidecar_init (GabbleConsoleSidecar *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_CONSOLE_SIDECAR,
+ GabbleConsoleSidecarPrivate);
+ self->priv->reader = wocky_xmpp_reader_new_no_stream ();
+ self->priv->writer = wocky_xmpp_writer_new_no_stream ();
+}
+
+static void
+gabble_console_sidecar_set_property (
+ GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GabbleConsoleSidecar *self = GABBLE_CONSOLE_SIDECAR (object);
+
+ switch (property_id)
+ {
+ case PROP_CONNECTION:
+ g_assert (self->priv->connection == NULL); /* construct-only */
+ self->priv->connection = g_value_dup_object (value);
+ break;
+
+ case PROP_SESSION:
+ g_assert (self->priv->session == NULL); /* construct-only */
+ self->priv->session = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+ }
+}
+
+static void
+gabble_console_sidecar_dispose (GObject *object)
+{
+ void (*chain_up) (GObject *) =
+ G_OBJECT_CLASS (gabble_console_sidecar_parent_class)->dispose;
+ GabbleConsoleSidecar *self = GABBLE_CONSOLE_SIDECAR (object);
+
+ tp_clear_object (&self->priv->connection);
+ tp_clear_object (&self->priv->reader);
+ tp_clear_object (&self->priv->writer);
+ tp_clear_object (&self->priv->session);
+
+ if (chain_up != NULL)
+ chain_up (object);
+}
+
+static void
+gabble_console_sidecar_class_init (GabbleConsoleSidecarClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = gabble_console_sidecar_set_property;
+ object_class->dispose = gabble_console_sidecar_dispose;
+
+ g_type_class_add_private (klass, sizeof (GabbleConsoleSidecarPrivate));
+
+ g_object_class_install_property (object_class, PROP_CONNECTION,
+ g_param_spec_object ("connection", "Connection",
+ "Gabble connection",
+ GABBLE_TYPE_CONNECTION,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class, PROP_SESSION,
+ g_param_spec_object ("session", "Session",
+ "Wocky session",
+ WOCKY_TYPE_SESSION,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+}
+
+static void sidecar_iface_init (
+ gpointer g_iface,
+ gpointer data)
+{
+ GabbleSidecarInterface *iface = g_iface;
+
+ iface->interface = GABBLE_IFACE_GABBLE_PLUGIN_CONSOLE;
+ iface->get_immutable_properties = NULL;
+}
+
+static void
+return_from_send_iq (
+ GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GabbleConsoleSidecar *self = GABBLE_CONSOLE_SIDECAR (source);
+ DBusGMethodInvocation *context = user_data;
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+ GError *error = NULL;
+
+ if (g_simple_async_result_propagate_error (simple, &error))
+ {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ }
+ else
+ {
+ WockyStanza *reply = g_simple_async_result_get_op_res_gpointer (simple);
+ WockyStanzaSubType sub_type;
+ const guint8 *body;
+ gsize length;
+
+ wocky_stanza_get_type_info (reply, NULL, &sub_type);
+ wocky_xmpp_writer_write_stanza (self->priv->writer, reply, &body, &length);
+
+ /* woop woop */
+ gabble_svc_gabble_plugin_console_return_from_send_iq (context,
+ sub_type == WOCKY_STANZA_SUB_TYPE_RESULT ? "result" : "error",
+ (const gchar *) body);
+ }
+}
+
+static void
+console_iq_reply_cb (
+ GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ WockyPorter *porter = WOCKY_PORTER (source);
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+ GError *error = NULL;
+ WockyStanza *reply = wocky_porter_send_iq_finish (porter, result, &error);
+
+ if (reply != NULL)
+ {
+ g_simple_async_result_set_op_res_gpointer (simple, reply, g_object_unref);
+ }
+ else
+ {
+ g_simple_async_result_set_from_error (simple, error);
+ g_error_free (error);
+ }
+
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static gboolean
+get_iq_type (const gchar *type_str,
+ WockyStanzaSubType *sub_type_out,
+ GError **error)
+{
+ if (!wocky_strdiff (type_str, "get"))
+ {
+ *sub_type_out = WOCKY_STANZA_SUB_TYPE_GET;
+ return TRUE;
+ }
+
+ if (!wocky_strdiff (type_str, "set"))
+ {
+ *sub_type_out = WOCKY_STANZA_SUB_TYPE_SET;
+ return TRUE;
+ }
+
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "Type must be 'get' or 'set', not '%s'", type_str);
+ return FALSE;
+}
+
+static gboolean
+validate_jid (const gchar **to,
+ GError **error)
+{
+ if (tp_str_empty (*to))
+ {
+ *to = NULL;
+ return TRUE;
+ }
+
+ if (wocky_decode_jid (*to, NULL, NULL, NULL))
+ return TRUE;
+
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "'%s' is not a valid (or empty) JID", *to);
+ return FALSE;
+}
+
+static gboolean
+parse_body_fragment (
+ GabbleConsoleSidecar *self,
+ const gchar *body,
+ WockyNodeTree **fragment_out,
+ GError **error)
+{
+ GabbleConsoleSidecarPrivate *priv = self->priv;
+ WockyStanza *stanza;
+
+ wocky_xmpp_reader_reset (priv->reader);
+ wocky_xmpp_reader_push (priv->reader, (const guint8 *) body, strlen (body));
+
+ *error = wocky_xmpp_reader_get_error (priv->reader);
+
+ if (*error != NULL)
+ return FALSE;
+
+ stanza = wocky_xmpp_reader_pop_stanza (priv->reader);
+
+ if (stanza == NULL)
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+ "Incomplete stanza! Bad person.");
+ return FALSE;
+ }
+
+ *fragment_out = (WockyNodeTree *) stanza;
+ return TRUE;
+}
+
+static void
+console_send_iq (
+ GabbleSvcGabblePluginConsole *sidecar,
+ const gchar *type_str,
+ const gchar *to,
+ const gchar *body,
+ DBusGMethodInvocation *context)
+{
+ GabbleConsoleSidecar *self = GABBLE_CONSOLE_SIDECAR (sidecar);
+ WockyPorter *porter = wocky_session_get_porter (self->priv->session);
+ WockyStanzaSubType sub_type;
+ WockyNodeTree *fragment;
+ GError *error = NULL;
+
+ if (get_iq_type (type_str, &sub_type, &error) &&
+ validate_jid (&to, &error) &&
+ parse_body_fragment (self, body, &fragment, &error))
+ {
+ GSimpleAsyncResult *simple = g_simple_async_result_new (G_OBJECT (self),
+ return_from_send_iq, context, console_send_iq);
+ WockyStanza *stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, sub_type,
+ NULL, to, NULL);
+
+ wocky_node_add_node_tree (wocky_stanza_get_top_node (stanza), fragment);
+ wocky_porter_send_iq_async (porter, stanza, NULL, console_iq_reply_cb, simple);
+ g_object_unref (fragment);
+ }
+ else
+ {
+ DEBUG ("%s", error->message);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ }
+}
+
+static void
+console_iface_init (
+ gpointer klass,
+ gpointer data G_GNUC_UNUSED)
+{
+#define IMPLEMENT(x) gabble_svc_gabble_plugin_console_implement_##x (\
+ klass, console_##x)
+ IMPLEMENT (send_iq);
+#undef IMPLEMENT
+}
diff --git a/gabble/plugins/console.h b/gabble/plugins/console.h
new file mode 100644
index 000000000..e3e2c0304
--- /dev/null
+++ b/gabble/plugins/console.h
@@ -0,0 +1,85 @@
+/* XML console plugin
+ *
+ * Copyright © 2011 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <glib-object.h>
+
+#include <gio/gio.h>
+#include <wocky/wocky-session.h>
+
+typedef struct _GabbleConsolePlugin GabbleConsolePlugin;
+typedef struct _GabbleConsolePluginClass GabbleConsolePluginClass;
+typedef struct _GabbleConsolePluginPrivate GabbleConsolePluginPrivate;
+
+struct _GabbleConsolePlugin {
+ GObject parent;
+ GabbleConsolePluginPrivate *priv;
+};
+
+struct _GabbleConsolePluginClass {
+ GObjectClass parent;
+};
+
+GType gabble_console_plugin_get_type (void);
+
+#define GABBLE_TYPE_CONSOLE_PLUGIN \
+ (gabble_console_plugin_get_type ())
+#define GABBLE_CONSOLE_PLUGIN(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GABBLE_TYPE_CONSOLE_PLUGIN, \
+ GabbleConsolePlugin))
+#define GABBLE_CONSOLE_PLUGIN_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), GABBLE_TYPE_CONSOLE_PLUGIN, \
+ GabbleConsolePluginClass))
+#define GABBLE_IS_CONSOLE_PLUGIN(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GABBLE_TYPE_CONSOLE_PLUGIN))
+#define GABBLE_IS_CONSOLE_PLUGIN_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), GABBLE_TYPE_CONSOLE_PLUGIN))
+#define GABBLE_CONSOLE_PLUGIN_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_CONSOLE_PLUGIN, \
+ GabbleConsolePluginClass))
+
+typedef struct _GabbleConsoleSidecar GabbleConsoleSidecar;
+typedef struct _GabbleConsoleSidecarClass GabbleConsoleSidecarClass;
+typedef struct _GabbleConsoleSidecarPrivate GabbleConsoleSidecarPrivate;
+
+struct _GabbleConsoleSidecar {
+ GObject parent;
+ GabbleConsoleSidecarPrivate *priv;
+};
+
+struct _GabbleConsoleSidecarClass {
+ GObjectClass parent;
+};
+
+GType gabble_console_sidecar_get_type (void);
+
+#define GABBLE_TYPE_CONSOLE_SIDECAR \
+ (gabble_console_sidecar_get_type ())
+#define GABBLE_CONSOLE_SIDECAR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GABBLE_TYPE_CONSOLE_SIDECAR, \
+ GabbleConsoleSidecar))
+#define GABBLE_CONSOLE_SIDECAR_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), GABBLE_TYPE_CONSOLE_SIDECAR, \
+ GabbleConsoleSidecarClass))
+#define GABBLE_IS_CONSOLE_SIDECAR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GABBLE_TYPE_CONSOLE_SIDECAR))
+#define GABBLE_IS_CONSOLE_SIDECAR_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), GABBLE_TYPE_CONSOLE_SIDECAR))
+#define GABBLE_CONSOLE_SIDECAR_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_CONSOLE_SIDECAR, \
+ GabbleConsoleSidecarClass))