summaryrefslogtreecommitdiff
path: root/plugin-base
diff options
context:
space:
mode:
authorJonny Lamb <jonny.lamb@collabora.co.uk>2011-09-05 16:30:20 +0100
committerJonny Lamb <jonny.lamb@collabora.co.uk>2011-09-06 11:43:02 +0100
commitebc9b3a24bb537784415f6e1e75a84c7197dd6da (patch)
tree0caa3f961a1043dd30d01d9f156d6e7a2de89892 /plugin-base
parent87df2bc27a610a6c815fd1c4c59c256990552dfe (diff)
salut: move more common files to plugin-base
"ifdef soup" Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
Diffstat (limited to 'plugin-base')
-rw-r--r--plugin-base/Makefile.am4
-rw-r--r--plugin-base/caps-manager.c4
-rw-r--r--plugin-base/channel-manager.c553
-rw-r--r--plugin-base/channel-manager.h64
-rw-r--r--plugin-base/ytstenut.c189
-rw-r--r--plugin-base/ytstenut.h60
6 files changed, 874 insertions, 0 deletions
diff --git a/plugin-base/Makefile.am b/plugin-base/Makefile.am
index dfaa9f9..f1e676e 100644
--- a/plugin-base/Makefile.am
+++ b/plugin-base/Makefile.am
@@ -1,5 +1,9 @@
EXTRA_DIST = \
caps-manager.c \
caps-manager.h \
+ channel-manager.c \
+ channel-manager.h \
+ ytstenut.c \
+ ytstenut.h \
utils.c \
utils.h
diff --git a/plugin-base/caps-manager.c b/plugin-base/caps-manager.c
index be61ef1..73d34fc 100644
--- a/plugin-base/caps-manager.c
+++ b/plugin-base/caps-manager.c
@@ -241,7 +241,11 @@ caps_channel_manager_iface_init (
gpointer g_iface,
gpointer data G_GNUC_UNUSED)
{
+#ifdef SALUT /* sigh */
GabbleCapsChannelManagerIface *iface = g_iface;
+#else
+ GabbleCapsChannelManagerInterface *iface = g_iface;
+#endif
iface->represent_client = ytst_caps_manager_represent_client;
}
diff --git a/plugin-base/channel-manager.c b/plugin-base/channel-manager.c
new file mode 100644
index 0000000..9d81168
--- /dev/null
+++ b/plugin-base/channel-manager.c
@@ -0,0 +1,553 @@
+/*
+ * channel-manager.c - Source for YtstChannelManager
+ * Copyright (C) 2011 Intel, Corp.
+ * Copyright (C) 2005, 2011 Collabora Ltd.
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "message-channel.h"
+#include "channel-manager.h"
+#include "utils.h"
+
+#include <telepathy-glib/channel-manager.h>
+#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/gtypes.h>
+#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/util.h>
+
+#include <wocky/wocky-session.h>
+
+#ifdef SALUT
+#include <salut/caps-channel-manager.h>
+#else
+#include <gabble/caps-channel-manager.h>
+#endif
+
+#include <telepathy-ytstenut-glib/telepathy-ytstenut-glib.h>
+
+#define DEBUG(msg, ...) \
+ g_debug ("%s: " msg, G_STRFUNC, ##__VA_ARGS__)
+
+static void ytst_channel_manager_iface_init (gpointer g_iface,
+ gpointer iface_data);
+static void ytst_caps_channel_manager_iface_init (gpointer g_iface,
+ gpointer iface_data);
+
+G_DEFINE_TYPE_WITH_CODE (YtstChannelManager, ytst_channel_manager, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER,
+ ytst_channel_manager_iface_init);
+ G_IMPLEMENT_INTERFACE (GABBLE_TYPE_CAPS_CHANNEL_MANAGER,
+ ytst_caps_channel_manager_iface_init);
+);
+
+/* properties */
+enum
+{
+ PROP_CONNECTION = 1,
+ LAST_PROPERTY
+};
+
+/* private structure */
+struct _YtstChannelManagerPrivate
+{
+#ifdef SALUT
+ SalutConnection *connection;
+#else
+ GabbleConnection *connection;
+#endif
+ GQueue *channels;
+ gulong status_changed_id;
+ guint message_handler_id;
+ gboolean dispose_has_run;
+};
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+static void
+on_channel_closed (YtstMessageChannel *channel,
+ gpointer user_data)
+{
+ YtstChannelManager *self = YTST_CHANNEL_MANAGER (user_data);
+ YtstChannelManagerPrivate *priv = self->priv;
+
+ tp_channel_manager_emit_channel_closed_for_object (self,
+ TP_EXPORTABLE_CHANNEL (channel));
+
+ if (priv->channels != NULL)
+ {
+ DEBUG ("Removing channel %p", channel);
+ g_queue_remove (priv->channels, channel);
+ }
+}
+
+static void
+manager_take_ownership_of_channel (YtstChannelManager *self,
+ YtstMessageChannel *channel)
+{
+ YtstChannelManagerPrivate *priv = self->priv;
+
+ /* Takes ownership of channel */
+ g_assert (g_queue_index (priv->channels, channel) == -1);
+ g_queue_push_tail (priv->channels, channel);
+
+ g_signal_connect (channel, "closed", G_CALLBACK (on_channel_closed), self);
+}
+
+static gboolean
+message_stanza_callback (WockyPorter *porter,
+ WockyStanza *stanza,
+ gpointer user_data)
+{
+ YtstChannelManager *self = YTST_CHANNEL_MANAGER (user_data);
+ YtstChannelManagerPrivate *priv = self->priv;
+
+ WockyNode *top;
+ WockyStanzaSubType sub_type = WOCKY_STANZA_SUB_TYPE_NONE;
+
+ TpBaseConnection *base_conn = TP_BASE_CONNECTION (priv->connection);
+ TpHandleRepoIface *handle_repo = tp_base_connection_get_handles (base_conn,
+ TP_HANDLE_TYPE_CONTACT);
+ YtstMessageChannel *channel;
+ TpHandle handle;
+#ifdef SALUT
+ WockyContact *contact = wocky_stanza_get_from_contact (stanza);
+#endif
+ gchar *jid;
+
+ /* needs to be type get or set */
+ wocky_stanza_get_type_info (stanza, NULL, &sub_type);
+ if (sub_type != WOCKY_STANZA_SUB_TYPE_GET
+ && sub_type != WOCKY_STANZA_SUB_TYPE_SET)
+ return FALSE;
+
+ /* we must have an ID */
+ top = wocky_stanza_get_top_node (stanza);
+ if (wocky_node_get_attribute (top, "id") == NULL)
+ return FALSE;
+
+#ifdef SALUT
+ jid = wocky_contact_dup_jid (WOCKY_CONTACT (contact));
+#else
+ jid = g_strdup (wocky_stanza_get_from (stanza));
+#endif
+ handle = tp_handle_lookup (handle_repo, jid, NULL, NULL);
+ if (handle == 0)
+ {
+ g_free (jid);
+ return FALSE;
+ }
+
+ channel = ytst_message_channel_new (priv->connection,
+#ifdef SALUT
+ WOCKY_LL_CONTACT (contact),
+#else
+ jid,
+#endif
+ stanza, handle, handle, FALSE);
+ manager_take_ownership_of_channel (self, channel);
+ tp_channel_manager_emit_new_channel (self, TP_EXPORTABLE_CHANNEL (channel),
+ NULL);
+
+ g_free (jid);
+
+ return TRUE;
+}
+
+static void
+manager_close_all (YtstChannelManager *self)
+{
+ YtstChannelManagerPrivate *priv = self->priv;
+
+ if (priv->channels != NULL)
+ {
+ DEBUG ("closing channels");
+ g_queue_foreach (priv->channels, (GFunc) tp_base_channel_close, NULL);
+ g_queue_foreach (priv->channels, (GFunc) g_object_unref, NULL);
+ g_queue_free (priv->channels);
+ priv->channels = NULL;
+ }
+
+ if (priv->status_changed_id != 0UL)
+ {
+ g_signal_handler_disconnect (priv->connection, priv->status_changed_id);
+ priv->status_changed_id = 0UL;
+ }
+}
+
+static void
+on_connection_status_changed (TpBaseConnection *conn,
+ guint status,
+ guint reason,
+ YtstChannelManager *self)
+{
+ if (status == TP_CONNECTION_STATUS_DISCONNECTED)
+ manager_close_all (self);
+}
+
+/* -----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+ytst_channel_manager_init (YtstChannelManager *self)
+{
+ YtstChannelManagerPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ YTST_TYPE_CHANNEL_MANAGER, YtstChannelManagerPrivate);
+ self->priv = priv;
+}
+
+static void
+ytst_channel_manager_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ YtstChannelManager *self = YTST_CHANNEL_MANAGER (object);
+ YtstChannelManagerPrivate *priv = self->priv;
+
+ switch (property_id)
+ {
+ case PROP_CONNECTION:
+ g_value_set_object (value, priv->connection);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+ytst_channel_manager_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ YtstChannelManager *self = YTST_CHANNEL_MANAGER (object);
+ YtstChannelManagerPrivate *priv = self->priv;
+
+ switch (property_id)
+ {
+ case PROP_CONNECTION:
+ priv->connection = g_value_get_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+ytst_channel_manager_constructed (GObject *object)
+{
+ YtstChannelManager *self = YTST_CHANNEL_MANAGER (object);
+ YtstChannelManagerPrivate *priv = self->priv;
+ WockySession *session;
+
+ priv->channels = g_queue_new ();
+
+#ifdef SALUT
+ session = salut_connection_get_session (priv->connection);
+#else
+ session = gabble_connection_get_session (priv->connection);
+#endif
+
+ priv->message_handler_id = wocky_porter_register_handler_from_anyone (
+ wocky_session_get_porter (session),
+ WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE,
+ WOCKY_PORTER_HANDLER_PRIORITY_NORMAL,
+ message_stanza_callback, self,
+ '(', "message",
+ ':', YTST_MESSAGE_NS,
+ ')', NULL);
+
+ priv->status_changed_id = g_signal_connect (priv->connection,
+ "status-changed", (GCallback) on_connection_status_changed, self);
+
+ if (G_OBJECT_CLASS (ytst_channel_manager_parent_class)->constructed)
+ G_OBJECT_CLASS (ytst_channel_manager_parent_class)->constructed (object);
+}
+
+static void
+ytst_channel_manager_dispose (GObject *object)
+{
+ YtstChannelManager *self = YTST_CHANNEL_MANAGER (object);
+ YtstChannelManagerPrivate *priv = self->priv;
+ WockySession *session;
+
+ if (priv->dispose_has_run)
+ return;
+
+ priv->dispose_has_run = TRUE;
+
+#ifdef SALUT
+ session = salut_connection_get_session (priv->connection);
+#else
+ session = gabble_connection_get_session (priv->connection);
+#endif
+
+ if (session != NULL)
+ {
+ wocky_porter_unregister_handler (
+ wocky_session_get_porter (session),
+ priv->message_handler_id);
+ }
+ priv->message_handler_id = 0;
+
+ manager_close_all (self);
+
+ if (G_OBJECT_CLASS (ytst_channel_manager_parent_class)->dispose)
+ G_OBJECT_CLASS (ytst_channel_manager_parent_class)->dispose (object);
+}
+
+static void
+ytst_channel_manager_class_init (YtstChannelManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GParamSpec *param_spec;
+
+ g_type_class_add_private (klass, sizeof (YtstChannelManagerPrivate));
+
+ object_class->constructed = ytst_channel_manager_constructed;
+ object_class->dispose = ytst_channel_manager_dispose;
+ object_class->get_property = ytst_channel_manager_get_property;
+ object_class->set_property = ytst_channel_manager_set_property;
+
+ param_spec = g_param_spec_object (
+ "connection",
+ "TpBaseConnection object",
+ "Connection object that owns this channel factory object.",
+ TP_TYPE_BASE_CONNECTION,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
+}
+
+typedef struct
+{
+ TpExportableChannelFunc func;
+ gpointer data;
+} foreach_closure;
+
+static void
+run_foreach_one (gpointer value,
+ gpointer data)
+{
+ TpExportableChannel *chan = TP_EXPORTABLE_CHANNEL (value);
+ foreach_closure *f = data;
+ f->func (chan, f->data);
+}
+
+static void
+ytst_channel_manager_foreach_channel (TpChannelManager *iface,
+ TpExportableChannelFunc func,
+ gpointer user_data)
+{
+ YtstChannelManager *self = YTST_CHANNEL_MANAGER (iface);
+ YtstChannelManagerPrivate *priv = self->priv;
+ foreach_closure f = { func, user_data };
+
+ g_queue_foreach (priv->channels, run_foreach_one, &f);
+}
+
+static const gchar * const channel_fixed_properties[] = {
+ TP_IFACE_CHANNEL ".ChannelType",
+ TP_IFACE_CHANNEL ".TargetHandleType",
+ TP_YTS_IFACE_CHANNEL ".RequestType",
+ NULL
+};
+
+
+static const gchar * const channel_allowed_properties[] = {
+ TP_IFACE_CHANNEL ".TargetHandle",
+ TP_IFACE_CHANNEL ".TargetID",
+ TP_YTS_IFACE_CHANNEL ".RequestType",
+ TP_YTS_IFACE_CHANNEL ".RequestAttributes",
+ TP_YTS_IFACE_CHANNEL ".RequestBody",
+ TP_YTS_IFACE_CHANNEL ".TargetService",
+ TP_YTS_IFACE_CHANNEL ".InitiatorService",
+ NULL
+};
+
+static void
+ytst_channel_manager_type_foreach_channel_class (GType type,
+ TpChannelManagerTypeChannelClassFunc func,
+ gpointer user_data)
+{
+ GHashTable *table = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify) tp_g_value_slice_free);
+ GValue *value;
+
+ value = tp_g_value_slice_new (G_TYPE_STRING);
+ g_value_set_static_string (value, TP_YTS_IFACE_CHANNEL);
+ g_hash_table_insert (table, (gchar *) channel_fixed_properties[0],
+ value);
+
+ value = tp_g_value_slice_new (G_TYPE_UINT);
+ g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT);
+ g_hash_table_insert (table, (gchar *) channel_fixed_properties[1],
+ value);
+
+ func (type, table, channel_allowed_properties, user_data);
+
+ g_hash_table_destroy (table);
+}
+
+static gboolean
+ytst_channel_manager_create_channel (TpChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
+{
+ YtstChannelManager *self = YTST_CHANNEL_MANAGER (manager);
+ YtstChannelManagerPrivate *priv = self->priv;
+ TpBaseConnection *base_conn = (TpBaseConnection *) priv->connection;
+ TpHandleRepoIface *handle_repo = tp_base_connection_get_handles (
+ base_conn, TP_HANDLE_TYPE_CONTACT);
+ TpHandle handle;
+ GError *error = NULL;
+ const gchar *name;
+#ifdef SALUT
+ WockySession *session;
+ WockyContactFactory *factory;
+ WockyLLContact *contact;
+#else
+ TpHandle self_handle;
+#endif
+ WockyStanza *request;
+ GSList *tokens = NULL;
+ YtstMessageChannel *channel;
+
+ if (tp_strdiff (tp_asv_get_string (request_properties,
+ TP_IFACE_CHANNEL ".ChannelType"),
+ TP_YTS_IFACE_CHANNEL))
+ return FALSE;
+
+ if (tp_asv_get_uint32 (request_properties,
+ TP_IFACE_CHANNEL ".TargetHandleType", NULL) != TP_HANDLE_TYPE_CONTACT)
+ return FALSE;
+
+ handle = tp_asv_get_uint32 (request_properties,
+ TP_IFACE_CHANNEL ".TargetHandle", NULL);
+
+ if (!tp_handle_is_valid (handle_repo, handle, &error))
+ goto error;
+
+ /* Check if there are any other properties that we don't understand */
+ if (tp_channel_manager_asv_has_unknown_properties (request_properties,
+ channel_fixed_properties, channel_allowed_properties, &error))
+ goto error;
+
+ name = tp_handle_inspect (handle_repo, handle);
+ DEBUG ("Requested channel for handle: %u (%s)", handle, name);
+
+#ifdef SALUT
+ session = salut_connection_get_session (priv->connection);
+ factory = wocky_session_get_contact_factory (session);
+ contact = wocky_contact_factory_lookup_ll_contact (factory, name);
+ if (contact == NULL)
+ {
+ g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ "%s is not online", name);
+ goto error;
+ }
+#else
+ self_handle = tp_base_connection_get_self_handle (base_conn);
+#endif
+
+ request = ytst_message_channel_build_request (request_properties,
+#ifdef SALUT
+ salut_connection_get_name (priv->connection), contact,
+#else
+ tp_handle_inspect (handle_repo, self_handle), name,
+#endif
+ &error);
+ if (request == NULL)
+ goto error;
+
+ channel = ytst_message_channel_new (priv->connection,
+#ifdef SALUT
+ contact,
+#else
+ name,
+#endif
+ request, handle, base_conn->self_handle, TRUE);
+ manager_take_ownership_of_channel (self, channel);
+
+ g_object_unref (request);
+
+ if (request_token != NULL)
+ tokens = g_slist_prepend (tokens, request_token);
+ tp_channel_manager_emit_new_channel (self, TP_EXPORTABLE_CHANNEL (channel),
+ tokens);
+
+ return TRUE; /* We will handle this one */
+
+error:
+ g_return_val_if_fail (error, FALSE);
+ tp_channel_manager_emit_request_failed (self, request_token,
+ error->domain, error->code, error->message);
+ g_error_free (error);
+ return TRUE; /* We tried to handle */
+}
+
+static void
+ytst_channel_manager_iface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+ TpChannelManagerIface *iface = g_iface;
+
+ iface->foreach_channel = ytst_channel_manager_foreach_channel;
+ iface->type_foreach_channel_class =
+ ytst_channel_manager_type_foreach_channel_class;
+
+ /*
+ * Each channel only supports one request/reply, so we create
+ * a channel and never reuse. Same implementation for all three.
+ */
+ iface->create_channel = ytst_channel_manager_create_channel;
+ iface->request_channel = ytst_channel_manager_create_channel;
+ iface->ensure_channel = ytst_channel_manager_create_channel;
+}
+
+static void
+ytst_caps_channel_manager_iface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+#ifdef SALUT /* sigh */
+ GabbleCapsChannelManagerIface *iface = g_iface;
+#else
+ GabbleCapsChannelManagerInterface *iface = g_iface;
+#endif
+
+ /* we don't need any of these */
+ iface->reset_caps = NULL;
+ iface->get_contact_caps = NULL;
+ iface->represent_client = NULL;
+}
+
+/* public functions */
+YtstChannelManager *
+ytst_channel_manager_new (TpBaseConnection *connection)
+{
+ return g_object_new (YTST_TYPE_CHANNEL_MANAGER,
+ "connection", connection,
+ NULL);
+}
diff --git a/plugin-base/channel-manager.h b/plugin-base/channel-manager.h
new file mode 100644
index 0000000..13b27a5
--- /dev/null
+++ b/plugin-base/channel-manager.h
@@ -0,0 +1,64 @@
+/*
+ * channel-manager.h - Header for YtstChannelManager
+ * Copyright (C) 2011 Intel, Corp.
+ * Copyright (C) 2005, 2011 Collabora Ltd.
+ *
+ * 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
+ */
+
+#ifndef __YTST_CHANNEL_MANAGER_H__
+#define __YTST_CHANNEL_MANAGER_H__
+
+#include <glib-object.h>
+
+#include <telepathy-glib/base-connection.h>
+
+G_BEGIN_DECLS
+
+typedef struct _YtstChannelManager YtstChannelManager;
+typedef struct _YtstChannelManagerClass YtstChannelManagerClass;
+typedef struct _YtstChannelManagerPrivate YtstChannelManagerPrivate;
+
+struct _YtstChannelManagerClass {
+ GObjectClass parent_class;
+};
+
+struct _YtstChannelManager {
+ GObject parent;
+ YtstChannelManagerPrivate *priv;
+};
+
+
+GType ytst_channel_manager_get_type (void);
+
+/* TYPE MACROS */
+#define YTST_TYPE_CHANNEL_MANAGER \
+ (ytst_channel_manager_get_type ())
+#define YTST_CHANNEL_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), YTST_TYPE_CHANNEL_MANAGER, YtstChannelManager))
+#define YTST_CHANNEL_MANAGER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), YTST_TYPE_CHANNEL_MANAGER, \
+ YtstChannelManagerClass))
+#define YTST_IS_CHANNEL_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), YTST_TYPE_CHANNEL_MANAGER))
+#define YTST_IS_CHANNEL_MANAGER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), YTST_TYPE_CHANNEL_MANAGER))
+#define YTST_CHANNEL_MANAGER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), YTST_TYPE_CHANNEL_MANAGER, \
+ YtstChannelManagerClass))
+
+YtstChannelManager * ytst_channel_manager_new (TpBaseConnection *connection);
+
+#endif /* #ifndef __YTST_CHANNEL_MANAGER_H__*/
diff --git a/plugin-base/ytstenut.c b/plugin-base/ytstenut.c
new file mode 100644
index 0000000..f2a7662
--- /dev/null
+++ b/plugin-base/ytstenut.c
@@ -0,0 +1,189 @@
+/*
+ * ytstenut.c - Source for YstPlugin
+ *
+ * Copyright (C) 2011 Intel Corp.
+ *
+ * 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 "config.h"
+
+#include "ytstenut.h"
+
+#include "caps-manager.h"
+#include "status.h"
+#include "channel-manager.h"
+
+#ifdef SALUT
+#include <salut/plugin.h>
+#include <salut/protocol.h>
+#else
+#include <gabble/plugin.h>
+#endif
+
+#include <telepathy-ytstenut-glib/telepathy-ytstenut-glib.h>
+
+#define DEBUG(msg, ...) \
+ g_debug ("%s: " msg, G_STRFUNC, ##__VA_ARGS__)
+
+static const gchar * const sidecar_interfaces[] = {
+ TP_YTS_IFACE_STATUS,
+ NULL
+};
+
+static void plugin_iface_init (gpointer g_iface, gpointer data);
+
+G_DEFINE_TYPE_WITH_CODE (YtstPlugin, ytst_plugin, G_TYPE_OBJECT,
+#ifdef SALUT
+ G_IMPLEMENT_INTERFACE (SALUT_TYPE_PLUGIN, plugin_iface_init);
+#else
+ G_IMPLEMENT_INTERFACE (GABBLE_TYPE_PLUGIN, plugin_iface_init);
+#endif
+ )
+
+static void
+ytst_plugin_init (YtstPlugin *object)
+{
+ DEBUG ("%p", object);
+}
+
+static void
+ytst_plugin_class_init (YtstPluginClass *klass)
+{
+}
+
+#ifdef SALUT
+static void
+ytstenut_plugin_initialize (SalutPlugin *plugin,
+ TpBaseConnectionManager *connection_manager)
+{
+ TpBaseProtocol *protocol;
+
+ DEBUG ("%p on connection manager %p", plugin, connection_manager);
+
+ protocol = salut_protocol_new (G_TYPE_NONE,
+ "_ytstenut._tcp", "local-ytstenut", "Ytstenut protocol", "im-ytstenut");
+ tp_base_connection_manager_add_protocol (connection_manager, protocol);
+}
+#endif
+
+static void
+ytstenut_plugin_create_sidecar (
+#ifdef SALUT
+ SalutPlugin *plugin,
+#else
+ GabblePlugin *plugin,
+#endif
+ const gchar *sidecar_interface,
+#ifdef SALUT
+ SalutConnection *connection,
+#else
+ GabbleConnection *connection,
+#endif
+ WockySession *session,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (plugin),
+ callback, user_data,
+ /* sic: all plugins share {salut,gabble}_plugin_create_sidecar_finish() so we
+ * need to use the same source tag.
+ */
+#ifdef SALUT
+ salut_plugin_create_sidecar_async
+#else
+ gabble_plugin_create_sidecar
+#endif
+ );
+#ifdef SALUT
+ SalutSidecar *sidecar = NULL;
+#else
+ GabbleSidecar *sidecar = NULL;
+#endif
+
+ if (!tp_strdiff (sidecar_interface, TP_YTS_IFACE_STATUS))
+ {
+#ifdef SALUT
+ sidecar = SALUT_SIDECAR (ytst_status_new (session, connection));
+#else
+ sidecar = GABBLE_SIDECAR (ytst_status_new (session, connection));
+#endif
+ DEBUG ("created side car for: %s", TP_YTS_IFACE_STATUS);
+ }
+ 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 GPtrArray *
+ytstenut_plugin_create_channel_managers (
+#ifdef SALUT
+ SalutPlugin *plugin,
+#else
+ GabblePlugin *plugin,
+#endif
+ TpBaseConnection *connection)
+{
+ GPtrArray *ret = g_ptr_array_sized_new (1);
+
+ DEBUG ("%p on connection %p", plugin, connection);
+
+ g_ptr_array_add (ret, g_object_new (YTST_TYPE_CAPS_MANAGER, NULL));
+ g_ptr_array_add (ret, ytst_channel_manager_new (connection));
+
+ return ret;
+}
+
+static void
+plugin_iface_init (gpointer g_iface,
+ gpointer data G_GNUC_UNUSED)
+{
+#ifdef SALUT
+ SalutPluginInterface *iface = g_iface;
+#else
+ GabblePluginInterface *iface = g_iface;
+ #endif
+
+#ifdef SALUT
+ iface->api_version = SALUT_PLUGIN_CURRENT_VERSION;
+ iface->initialize = ytstenut_plugin_initialize;
+#endif
+
+ iface->name = "Ytstenut plugin";
+ iface->version = PACKAGE_VERSION;
+
+ iface->sidecar_interfaces = sidecar_interfaces;
+ iface->create_sidecar = ytstenut_plugin_create_sidecar;
+ iface->create_channel_managers = ytstenut_plugin_create_channel_managers;
+}
+
+#ifdef SALUT
+SalutPlugin *
+salut_plugin_create (void)
+#else
+GabblePlugin *
+gabble_plugin_create (void)
+#endif
+{
+ return g_object_new (YTST_TYPE_PLUGIN, NULL);
+}
diff --git a/plugin-base/ytstenut.h b/plugin-base/ytstenut.h
new file mode 100644
index 0000000..fdd5389
--- /dev/null
+++ b/plugin-base/ytstenut.h
@@ -0,0 +1,60 @@
+/*
+ * ytstenut.h - Header for YstPlugin
+ *
+ * Copyright (C) 2011 Intel Corp.
+ *
+ * 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>
+
+#ifndef YTST_PLUGIN_H
+#define YTST_PLUGIN_H
+
+G_BEGIN_DECLS
+
+typedef struct _YtstPluginClass YtstPluginClass;
+typedef struct _YtstPlugin YtstPlugin;
+
+struct _YtstPluginClass
+{
+ GObjectClass parent;
+};
+
+struct _YtstPlugin
+{
+ GObject parent;
+};
+
+GType ytst_plugin_get_type (void);
+
+#define YTST_TYPE_PLUGIN \
+ (ytst_plugin_get_type ())
+#define YTST_PLUGIN(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), YTST_TYPE_PLUGIN, YtstPlugin))
+#define YTST_PLUGIN_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), YTST_TYPE_PLUGIN, \
+ YtstPluginClass))
+#define YTST_IS_PLUGIN(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), YTST_TYPE_PLUGIN))
+#define YTST_IS_PLUGIN_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), YTST_TYPE_PLUGIN))
+#define YTST_PLUGIN_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), YTST_TYPE_PLUGIN, \
+ YtstPluginClass))
+
+G_END_DECLS
+
+#endif /* ifndef YTST_PLUGIN_H */