libtelepathy/src/tp-conn.c
changeset 0 d0f3a028347a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libtelepathy/src/tp-conn.c	Tue Feb 02 01:10:06 2010 +0200
@@ -0,0 +1,734 @@
+/* tp-conn.c
+ *
+ * Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <string.h>
+#include "tp-conn.h"
+#include "tp-helpers.h"
+#include "tp-connmgr.h"
+#include "tp-props-iface.h"
+
+
+
+#ifdef EMULATOR
+#include "libtelepathy_wsd_solution.h"
+#endif
+
+#ifdef EMULATOR
+	
+	GET_STATIC_VAR_FROM_TLS(parent_class,tp_conn,GObjectClass *)
+	#define parent_class (*GET_WSD_VAR_NAME(parent_class,tp_conn,s)())
+	
+	GET_STATIC_VAR_FROM_TLS(type1,tp_conn,GType)
+	#define type1 (*GET_WSD_VAR_NAME(type1,tp_conn,s)())
+	
+	GET_STATIC_VAR_FROM_TLS(ret1,tp_conn,GQuark)
+	#define ret1 (*GET_WSD_VAR_NAME(ret1,tp_conn,s)())
+	
+	GET_STATIC_VAR_FROM_TLS(ret2,tp_conn,GQuark)
+	#define ret2 (*GET_WSD_VAR_NAME(ret2,tp_conn,s)())
+	
+	GET_STATIC_VAR_FROM_TLS(ret3,tp_conn,GQuark)
+	#define ret3 (*GET_WSD_VAR_NAME(ret3,tp_conn,s)())
+	
+	GET_STATIC_VAR_FROM_TLS(ret4,tp_conn,GQuark)
+	#define ret4 (*GET_WSD_VAR_NAME(ret4,tp_conn,s)())
+	
+	GET_STATIC_VAR_FROM_TLS(ret5,tp_conn,GQuark)
+	#define ret5 (*GET_WSD_VAR_NAME(ret5,tp_conn,s)())
+	
+	GET_STATIC_VAR_FROM_TLS(ret6,tp_conn,GQuark)
+	#define ret6 (*GET_WSD_VAR_NAME(ret6,tp_conn,s)())
+	
+	GET_STATIC_VAR_FROM_TLS(ret7,tp_conn,GQuark)
+	#define ret7 (*GET_WSD_VAR_NAME(ret7,tp_conn,s)())
+	
+	GET_STATIC_VAR_FROM_TLS(ret8,tp_conn,GQuark)
+	#define ret8 (*GET_WSD_VAR_NAME(ret8,tp_conn,s)())
+	
+	GET_STATIC_VAR_FROM_TLS(ret9,tp_conn,GQuark)
+    #define ret9 (*GET_WSD_VAR_NAME(ret9,tp_conn,s)())
+	
+#else
+	static GObjectClass *parent_class = NULL;
+#endif
+
+
+
+static gboolean tp_conn_status_change_handler(DBusGProxy *proxy, 
+ 					      guint status, guint reason, 
+ 					      gpointer user_data); 
+
+static void _tp_conn_connect_req_handler(DBusGProxy *proxy,
+                                        GError *error, gpointer user_data);
+
+static void _tp_conn_register_signal_marshallers()
+{
+  /* Register marshaller for NewChannel signal */
+  dbus_g_object_register_marshaller(tp_conn_signals_marshal_VOID__OBJECT_STRING_UINT_UINT_BOOLEAN, G_TYPE_NONE, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_BOOLEAN, G_TYPE_INVALID);
+  /* Register marshaller for StatusChanged signal */
+  dbus_g_object_register_marshaller(tp_conn_signals_marshal_VOID__UINT_UINT, G_TYPE_NONE, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID);
+}
+
+static void _tp_conn_register_interface_signal_marshallers()
+{
+  /* Register marshaller for Aliasing interface signal AliasUpdate and
+     ContactInfo interface signal GotContactInfo*/
+  dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__UINT_STRING, G_TYPE_NONE, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID);
+  /* Register marshaller for Forwarding interface signal ForwardingChanged */
+  dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__UINT, G_TYPE_NONE, G_TYPE_UINT, G_TYPE_INVALID);
+  /* Register marshaller for Presence interface signal PresenceUpdate */
+  dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__BOXED, G_TYPE_NONE, G_TYPE_BOXED, G_TYPE_INVALID);
+  /* Register marshaller for Privacy interface signal PrivacyModeChanged */
+  dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__STRING, G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INVALID);
+  /* Register marshaller for Renaming interface signal Renamed */
+  dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__UINT_UINT, G_TYPE_NONE, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID);
+}
+
+
+/* We initialize the list of signatures here, so that we can use
+ * it to add them for new interface instances later.
+ */
+
+/* FIXME: This should be replaced by a more automatic way of doing
+ * this. The reason for using a set of function pointers is that there is no
+ * apparent cleaner way of doing this, unless DBusGProxy gains a non-varargs
+ * version of dbus_g_proxy_add_signal...
+ */
+
+static void _tp_conn_init_interface_signal_signatures(GData **signal_sigs)
+{
+  g_datalist_init(signal_sigs);
+
+  /* Create and store aliasing iface signal signatures */
+  g_datalist_id_set_data(signal_sigs, TELEPATHY_CONN_IFACE_ALIASING_QUARK,
+			 (gpointer)&tp_conn_set_aliasing_signatures);
+  /* Create and store capabilities iface signal signatures */
+  g_datalist_id_set_data(signal_sigs, TELEPATHY_CONN_IFACE_CAPABILITIES_QUARK,
+			 (gpointer)&tp_conn_set_capabilities_signatures);
+  /* Create and store contactinfo iface signal signatures */
+  g_datalist_id_set_data(signal_sigs, TELEPATHY_CONN_IFACE_CONTACTINFO_QUARK,
+			 (gpointer)&tp_conn_set_contactinfo_signatures);
+  /* Create and store forwarding iface signal signatures */
+  g_datalist_id_set_data(signal_sigs, TELEPATHY_CONN_IFACE_FORWARDING_QUARK,
+			 (gpointer)&tp_conn_set_forwarding_signatures);
+  /* Create and store presence iface signal signatures */
+  g_datalist_id_set_data(signal_sigs, TELEPATHY_CONN_IFACE_PRESENCE_QUARK,
+			 (gpointer)&tp_conn_set_presence_signatures);
+  /* Create and store privacy iface signal signatures */
+  g_datalist_id_set_data(signal_sigs, TELEPATHY_CONN_IFACE_PRIVACY_QUARK,
+			 (gpointer)&tp_conn_set_privacy_signatures);
+  /* Create and store renaming iface signal signatures */
+  g_datalist_id_set_data(signal_sigs, TELEPATHY_CONN_IFACE_RENAMING_QUARK,
+			 (gpointer)&tp_conn_set_renaming_signatures);
+  g_datalist_id_set_data(signal_sigs, TELEPATHY_CONN_IFACE_AVATAR_QUARK,
+               (gpointer)&tp_conn_set_avatar_signatures);
+}
+
+static void synthesize_status_changed(TpConn *conn);
+
+static void tp_conn_init(GTypeInstance *instance, gpointer g_class)
+{
+  TpConn *self = TELEPATHY_CONN(instance);
+
+  self->first_run = TRUE;
+}
+
+
+static void tp_conn_dispose(GObject *obj)
+{
+  TpConn *self = TELEPATHY_CONN(obj);
+      
+  if (self->first_run == TRUE)
+  {
+    self->first_run = FALSE;
+    synthesize_status_changed(self);
+    g_datalist_clear(&(self->interface_list));
+  }
+  
+  /* Call parent class dispose method */
+  if (G_OBJECT_CLASS(parent_class)->dispose)
+  {
+    G_OBJECT_CLASS(parent_class)->dispose(obj);
+  }
+
+}
+
+
+static void tp_conn_finalize(GObject *obj)
+{
+  if (G_OBJECT_CLASS(parent_class)->finalize)
+    {
+      G_OBJECT_CLASS(parent_class)->finalize(obj);
+    }
+
+}
+
+
+static void tp_conn_class_init(TpConnClass *klass)
+{
+  GObjectClass *obj = G_OBJECT_CLASS(klass);
+  parent_class = g_type_class_peek_parent(klass);
+
+  obj->set_property = parent_class->set_property;
+  obj->get_property = parent_class->get_property;
+
+  obj->dispose = tp_conn_dispose;
+  obj->finalize = tp_conn_finalize;
+  _tp_conn_register_signal_marshallers();
+  _tp_conn_register_interface_signal_marshallers();
+  _tp_conn_init_interface_signal_signatures(&(klass->iface_signal_sigs));
+}
+
+#ifdef SYMBIAN
+EXPORT_C
+#endif
+GType tp_conn_get_type(void)
+{
+#ifndef EMULATOR
+  static GType type1 = 0;
+#endif
+  
+  if (type1 == 0)
+    {
+      static const GTypeInfo info = 
+	{
+	  sizeof(TpConnClass),
+	  NULL,
+	  NULL,
+	  (GClassInitFunc)tp_conn_class_init,
+	  NULL,
+	  NULL,
+	  sizeof(TpConn),
+	  0,
+	  (GInstanceInitFunc)tp_conn_init
+	  
+	};
+      type1 = g_type_register_static(DBUS_TYPE_G_PROXY,
+				    "TpConn", &info, 0);
+    }
+  return type1;
+}
+
+/* The interface name getters */
+
+GQuark tp_get_conn_interface()
+{
+#ifndef EMULATOR
+  static GQuark ret1 = 0;
+#endif
+
+  if (ret1 == 0)
+  {
+    /* FIXME: The naming conventions should be unified */
+    ret1 = g_quark_from_static_string(TP_IFACE_CONN_INTERFACE);
+  }
+
+  return ret1;
+}
+
+GQuark tp_get_conn_aliasing_interface()
+{
+#ifndef EMULATOR
+  static GQuark ret2 = 0;
+#endif
+
+  if (ret2 == 0)
+  {
+    ret2 = g_quark_from_static_string(TP_IFACE_CONN_INTERFACE_ALIASING);
+  }
+
+  return ret2;
+}
+
+GQuark tp_get_conn_capabilities_interface()
+{
+#ifndef EMULATOR
+  static GQuark ret3 = 0;
+#endif
+
+  if (ret3 == 0)
+  {
+    ret3 = g_quark_from_static_string(TP_IFACE_CONN_INTERFACE_CAPABILITIES);
+  }
+
+  return ret3;
+}
+
+GQuark tp_get_conn_contactinfo_interface()
+{
+#ifndef EMULATOR
+  static GQuark ret4 = 0;
+#endif
+
+  if (ret4 == 0)
+  {
+    ret4 = g_quark_from_static_string(TP_IFACE_CONN_INTERFACE_CONTACT_INFO);
+  }
+
+  return ret4;
+}
+
+GQuark tp_get_conn_forwarding_interface()
+{
+#ifndef EMULATOR
+  static GQuark ret5 = 0;
+#endif
+
+  if (ret5 == 0)
+  {
+    ret5 = g_quark_from_static_string(TP_IFACE_CONN_INTERFACE_FORWARDING);
+  }
+
+  return ret5;
+}
+
+#ifdef SYMBIAN
+EXPORT_C
+#endif
+GQuark tp_get_conn_presence_interface()
+{
+#ifndef EMULATOR
+  static GQuark ret6 = 0;
+#endif
+
+  if (ret6 == 0)
+  {
+    ret6 = g_quark_from_static_string(TP_IFACE_CONN_INTERFACE_PRESENCE);
+  }
+
+  return ret6;
+}
+
+
+GQuark tp_get_conn_privacy_interface()
+{
+#ifndef EMULATOR
+  static GQuark ret7 = 0;
+#endif
+
+  if (ret7 == 0)
+  {
+    ret7 = g_quark_from_static_string(TP_IFACE_CONN_INTERFACE_PRIVACY);
+  }
+
+  return ret7;
+}
+
+
+
+GQuark tp_get_conn_renaming_interface()
+{
+#ifndef EMULATOR
+  static GQuark ret8 = 0;
+#endif
+
+  if (ret8 == 0)
+  {
+    ret8 = g_quark_from_static_string(TP_IFACE_CONN_INTERFACE_RENAMING);
+  }
+
+  return ret8;
+}
+
+#ifdef SYMBIAN
+EXPORT_C 
+#endif
+GQuark tp_get_conn_avatar_interface(void)
+    {
+#ifndef EMULATOR
+  static GQuark ret9 = 0;
+#endif
+
+  if (ret9 == 0)
+  {
+    ret9 = g_quark_from_static_string(TP_IFACE_CONN_INTERFACE_AVATAR);
+  }
+
+  return ret9;    
+    }
+
+TpConn *
+tp_conn_new_without_connect (DBusGConnection *connection,
+                             const gchar *bus_name,
+                             const gchar *object_path,
+                             guint *status,
+                             GError **error)
+{
+  gchar *unique_name;
+  gchar **interfaces;
+  guint conn_status = TP_CONN_STATUS_DISCONNECTED;
+  TpConn *obj;
+  GError *err = NULL;
+
+  g_return_val_if_fail (connection != NULL, NULL);
+  g_return_val_if_fail (bus_name != NULL, NULL);
+  g_return_val_if_fail (object_path, NULL);
+
+  /* Create the proxy object for this connection. It will be used to
+     perform the actual method calls over D-BUS. */
+
+  if (!dbus_g_proxy_call (tp_get_bus_proxy (), "GetNameOwner", error,
+        G_TYPE_STRING, bus_name, G_TYPE_INVALID,
+        G_TYPE_STRING, &unique_name, G_TYPE_INVALID))
+    {
+      return NULL;
+    }
+
+  obj = g_object_new (TELEPATHY_CONN_TYPE,
+      "name", unique_name,
+      "path", object_path,
+      "interface", TP_IFACE_CONN_INTERFACE,//TP_IFACE_CONNECTION,
+      "connection", connection,
+      NULL);
+  g_free (unique_name);
+
+  g_datalist_init (&(obj->interface_list));
+
+  //ADD_SIGNALS_FOR_CONNECTION (DBUS_G_PROXY (obj)); //commenting this bcoz header file not found 
+  //equivalent of above stmt
+  dbus_g_proxy_add_signal (DBUS_G_PROXY (obj), "NewChannel",\
+    DBUS_TYPE_G_OBJECT_PATH,\
+    G_TYPE_STRING,\
+    G_TYPE_UINT,\
+    G_TYPE_UINT,\
+    G_TYPE_BOOLEAN,\
+    G_TYPE_INVALID);\
+  dbus_g_proxy_add_signal (DBUS_G_PROXY (obj), "StatusChanged",\
+    G_TYPE_UINT,\
+    G_TYPE_UINT,\
+    G_TYPE_INVALID);
+
+  /* Check if the connection is already connected. If so, we can
+   * already perform GetInterfaces(). */
+
+  if (!tp_conn_get_status (DBUS_G_PROXY (obj), &conn_status, &err))
+    {
+      if (err != NULL)
+        g_propagate_error (error, err);
+
+      g_object_unref (obj);
+      return NULL;
+    }
+
+  if (conn_status == TP_CONN_STATUS_CONNECTED)
+    {
+      if (!tp_conn_get_interfaces (DBUS_G_PROXY (obj), &interfaces, &err))
+        {
+          if (err != NULL)
+            g_propagate_error (error, err);
+
+          g_object_unref (obj);
+          return NULL;
+        }
+
+      /* Initialize the interface objects for this TpConn object */
+      tp_conn_local_set_interfaces (obj, interfaces);
+
+      g_strfreev (interfaces);
+    }
+  else
+    {
+      /* Not connected yet, so this is really a new connection. Thus, we
+         have to hook up to StatusChanged signal to perform the
+         GetInterfaces when it goes Connected */
+
+      dbus_g_proxy_connect_signal (DBUS_G_PROXY (obj), "StatusChanged",
+          G_CALLBACK (tp_conn_status_change_handler), NULL, NULL);
+    }
+
+  if (status != NULL)
+    *status = conn_status;
+  return obj;
+}
+
+
+TpConn *
+tp_conn_new (DBusGConnection *connection,
+             const gchar *bus_name,
+             const gchar *object_path)
+{
+  GError *error = NULL;
+  guint status;
+  TpConn *obj;
+
+  g_return_val_if_fail (connection != NULL, NULL);
+  g_return_val_if_fail (bus_name != NULL, NULL);
+  g_return_val_if_fail (object_path, NULL);
+
+  obj = tp_conn_new_without_connect (connection, bus_name, object_path,
+      &status, &error);
+
+  if (obj == NULL)
+    {
+      /* either GetNameOwner, GetStatus or GetInterfaces failed */
+      if (error != NULL)
+        {
+          g_warning ("Failed to create connection for %s %s: %s", bus_name,
+              object_path, error->message);
+          g_error_free (error);
+        }
+      else
+        {
+          g_warning ("Failed to create connection for %s %s: error is NULL",
+              bus_name, object_path);
+        }
+
+      return NULL;
+    }
+
+  if (status != TP_CONN_STATUS_CONNECTED)
+    {
+      tp_conn_connect_async (DBUS_G_PROXY (obj), _tp_conn_connect_req_handler,
+          NULL);
+    }
+
+  return obj;
+}
+
+#ifdef SYMBIAN
+EXPORT_C
+#endif
+TpChan *tp_conn_new_channel(DBusGConnection *connection,
+			    TpConn *tp_conn, const gchar *bus_name,
+			    gchar *type, guint handle_type,
+			    guint handle, gboolean supress_handler)
+{
+  GError *error = NULL;
+  gchar *chan_object_path = NULL;
+  TpChan *new_chan = NULL;
+
+  g_return_val_if_fail(connection, NULL);
+  g_return_val_if_fail(TELEPATHY_IS_CONN(tp_conn), NULL);
+  g_return_val_if_fail(bus_name, NULL);
+  g_return_val_if_fail(type, NULL);
+
+  /* Request a new channel to be created by using the proxy object.
+     We also retrieve the object path for it here. */
+
+  if (!tp_conn_request_channel(DBUS_G_PROXY(tp_conn),
+                               type, handle_type, handle, supress_handler,
+                               &chan_object_path, &error))
+  {
+    g_warning("RequestChannel() failed: %s\n", error -> message);
+    
+    g_error_free(error);
+    return NULL;
+  }
+
+
+  /* Create the object to represent the channel */
+
+  new_chan = tp_chan_new(connection, bus_name, chan_object_path, type,
+                         handle_type, handle);
+                         
+                    
+  g_free(chan_object_path);
+
+
+
+  return new_chan;
+}
+
+
+void tp_conn_local_set_interfaces(TpConn *self, gchar **interfaces)
+{
+  gchar **temp_ifaces = NULL;
+  const gchar *bus_name = dbus_g_proxy_get_bus_name(DBUS_G_PROXY(self));
+  const gchar *object_path = dbus_g_proxy_get_path(DBUS_G_PROXY(self));
+
+  DBusGConnection *connection = tp_get_bus ();
+
+  if (interfaces == NULL || connection == NULL)
+  {
+    return;
+  }
+
+  /* Create and store the proxy objects for the connection interfaces. */
+  for (temp_ifaces = interfaces; *temp_ifaces; temp_ifaces++)
+  {
+    DBusGProxy *if_proxy;
+    GQuark key = g_quark_from_string(*temp_ifaces);
+
+    if (key == TELEPATHY_PROPS_IFACE_QUARK)
+      {
+        if_proxy = DBUS_G_PROXY (tp_props_iface_new (connection,
+                                                     bus_name, object_path));
+      }
+    else
+      {
+        if_proxy = dbus_g_proxy_new_for_name(connection, bus_name, object_path,
+                                             *temp_ifaces);
+        if (if_proxy != NULL)
+        {
+          GData *sig_list = TELEPATHY_CONN_GET_CLASS(self)->iface_signal_sigs;
+          void (*signature_setter_func)();
+
+          /* Does the interface have signals? If yes, add their signatures
+             for the interface instance */
+          signature_setter_func =
+            g_datalist_id_get_data(&sig_list, key);
+
+          if (signature_setter_func != NULL)
+          {
+            signature_setter_func(if_proxy);
+          }
+        }
+      }
+
+   if (if_proxy != NULL)
+    {
+      g_datalist_id_set_data_full(&(self->interface_list),
+      key, if_proxy, g_object_unref);
+    }
+
+  }
+}
+
+#ifdef SYMBIAN
+EXPORT_C
+#endif
+DBusGProxy *
+tp_conn_get_interface (TpConn *self,
+                       GQuark iface_quark)
+{
+  DBusGProxy *iface_proxy = NULL;
+
+  g_return_val_if_fail (self != NULL, NULL);
+  g_return_val_if_fail (iface_quark != 0, NULL);
+
+  iface_proxy = (DBusGProxy *) g_datalist_id_get_data (
+      &(self->interface_list), iface_quark);
+
+  return iface_proxy;
+}
+
+void
+_tp_conn_connect_req_handler (DBusGProxy *proxy,
+                              GError *error,
+                              gpointer user_data)
+{
+  /* The interfaces for the TpConn are set on the StatusChanged
+     handler when we get connected. Just print errors (if any)
+     here. */
+
+  if (error)
+  {
+    g_warning ("Could not perform Connect() for the connection, because: %s",
+               error->message);
+    g_error_free (error);
+    return;
+  }
+
+}
+
+static gboolean
+tp_conn_status_change_handler (DBusGProxy *proxy,
+                               guint status,
+                               guint reason,
+                               gpointer user_data)
+{
+  gchar **interfaces = NULL;
+  GError *error = NULL;
+  TpConn *tp_conn = (TpConn *) proxy;
+
+  /* If the connection is up, we can get the list of interfaces */
+  /* FIXME: At some point, we should switch to doing this asynchronously */
+
+  if (status == TP_CONN_STATUS_CONNECTED)
+    {
+      if (!tp_conn_get_interfaces (DBUS_G_PROXY (proxy), &interfaces, &error))
+        {
+          g_warning ("GetInterfaces failed: %s\n", error->message);
+          g_error_free (error);
+          return TRUE;
+        }
+
+      /* Initialize the interface objects for this TpConn object */
+
+      tp_conn_local_set_interfaces (tp_conn, interfaces);
+
+      g_strfreev (interfaces);
+
+      dbus_g_proxy_disconnect_signal (proxy, "StatusChanged",
+          G_CALLBACK (tp_conn_status_change_handler), NULL);
+    }
+
+  return TRUE;
+}
+
+
+static void synthesize_status_changed(TpConn *conn)
+{
+
+  DBusMessageIter iter;
+  DBusMessage *msg = NULL;
+  guint value;
+  GType uint_type = G_TYPE_UINT;
+  GArray *statuschanged_signal_types = g_array_new(FALSE, FALSE,
+                                                  sizeof(GType));
+                                                  
+  
+  if (!statuschanged_signal_types)
+  {
+    g_warning("%s: Could not allocate type array for StatusChanged",
+              G_STRFUNC);
+    return;
+  }
+
+  msg = dbus_message_new_signal(dbus_g_proxy_get_path(DBUS_G_PROXY(conn)),
+                                TP_IFACE_CONN_INTERFACE, "StatusChanged");
+
+  if (!msg)
+  {
+    g_warning("%s: Could not allocate message for StatusChanged signal",
+              G_STRFUNC);
+    g_array_free(statuschanged_signal_types, FALSE);
+    return;
+  }
+
+  dbus_message_iter_init_append(msg, &iter); 
+  value = TP_CONN_STATUS_DISCONNECTED; 
+  dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &value); 
+  value = TP_CONN_STATUS_REASON_NONE_SPECIFIED; 
+  dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &value);
+
+  /* TODO: It might be worth considering to setup/remove the array in
+     base_init/base_deinit to make it persist for the whole class */
+  
+  if (statuschanged_signal_types)
+  {
+    g_array_insert_val(statuschanged_signal_types, 0, uint_type);
+    g_array_insert_val(statuschanged_signal_types, 1, uint_type);
+  }
+  else
+  {
+    g_warning("%s: Could not allocate array for StatusChanged types",
+              G_STRFUNC);
+    dbus_message_unref(msg);
+    return;
+  }
+
+  g_signal_emit_by_name(DBUS_G_PROXY(conn), 
+                        TP_IFACE_CONN_SIGNAL_STATUSCHANGED_SYNTHESIZED, msg,
+                        statuschanged_signal_types);
+  g_array_free(statuschanged_signal_types, TRUE);
+  dbus_message_unref(msg);
+}