[Telepathy-commits] [telepathy-sofiasip/master] Implemented the Aliasing interface on TpsipConnection

Mikhail Zabaluev mikhail.zabaluev at nokia.com
Tue Oct 7 05:28:02 PDT 2008


---
 src/Makefile.am              |    2 +
 src/conn-aliasing.c          |  287 ++++++++++++++++++++++++++++++++++++++++++
 src/conn-aliasing.h          |   33 +++++
 src/sip-connection-helpers.c |   47 +++++++
 src/sip-connection-helpers.h |    6 +-
 src/sip-connection-private.h |    1 +
 src/sip-connection.c         |   56 +++++----
 7 files changed, 406 insertions(+), 26 deletions(-)
 create mode 100644 src/conn-aliasing.c
 create mode 100644 src/conn-aliasing.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 77e6394..d7548a3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -83,6 +83,8 @@ libtpsip_convenience_la_SOURCES = \
     sip-connection.c \
     sip-connection-manager.h \
     sip-connection-manager.c \
+    conn-aliasing.h \
+    conn-aliasing.c \
     debug.h \
     debug.c \
     media-factory.h \
diff --git a/src/conn-aliasing.c b/src/conn-aliasing.c
new file mode 100644
index 0000000..05206f0
--- /dev/null
+++ b/src/conn-aliasing.c
@@ -0,0 +1,287 @@
+/*
+ * conn-aliasing.c - Aliasing interface implementation for TpsipConnection
+ * Copyright (C) 2008 Nokia Corporation
+ *   @author Mikhail Zabaluev <mikhail.zabaluev at nokia.com>
+ *
+ * This work 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 work 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 work; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "conn-aliasing.h"
+
+#include <telepathy-glib/errors.h>
+#include <telepathy-glib/gtypes.h>
+#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/svc-connection.h>
+
+#include "sip-connection-helpers.h"
+
+#define DEBUG_FLAG TPSIP_DEBUG_CONNECTION
+#include "debug.h"
+
+static void
+tpsip_connection_get_alias_flags (TpSvcConnectionInterfaceAliasing *iface,
+                                  DBusGMethodInvocation *context)
+{
+  TpBaseConnection *base = TP_BASE_CONNECTION (iface);
+
+  TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
+
+  /* No server-side aliasing yet */
+  tp_svc_connection_interface_aliasing_return_from_get_alias_flags (
+      context, 0);
+}
+
+static gchar *
+conn_get_alias (TpsipConnection *self,
+                TpHandleRepoIface *contact_handles,
+                TpHandle handle)
+{
+  TpBaseConnection *base = (TpBaseConnection *) self;
+  gchar *alias = NULL;
+
+  if (handle == base->self_handle)
+    {
+      /* Get our user-settable alias from the connection property */
+      g_object_get (self, "alias", &alias, NULL);
+    }
+
+  if (alias == NULL)
+    {
+      const url_t *url;
+
+      url = tpsip_conn_get_contact_url (self, handle);
+      switch (url->url_type)
+        {
+        case url_sip:
+          /* Return the SIP URI stripped down to [user@]host */
+          if (url->url_user != NULL)
+            alias = g_strdup_printf ("%s@%s",
+                                     url->url_user, url->url_host);
+          else
+            alias = g_strdup (url->url_host);
+          break;
+        case url_tel:
+          /* Retrieve the telephone number */
+          alias = g_strdup (url->url_host);
+          break;
+        default:
+          /* Return the handle string as is */
+          alias = g_strdup (tp_handle_inspect (contact_handles, handle));
+        }
+    }
+
+  g_assert (alias != NULL);
+  DEBUG("handle %u got alias %s", handle, alias);
+
+  return alias;
+}
+
+static void
+tpsip_connection_request_aliases (TpSvcConnectionInterfaceAliasing *iface,
+                                  const GArray *contacts,
+                                  DBusGMethodInvocation *context)
+{
+  TpsipConnection *self = TPSIP_CONNECTION (iface);
+  TpBaseConnection *base = (TpBaseConnection *) self;
+  TpHandleRepoIface *contact_handles;
+  GArray *aliases;
+  gchar **res;
+  GError *error = NULL;
+  guint i;
+
+  TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
+
+  contact_handles = tp_base_connection_get_handles (base,
+      TP_HANDLE_TYPE_CONTACT);
+
+  if (!tp_handles_are_valid (contact_handles, contacts, FALSE, &error))
+    {
+      dbus_g_method_return_error (context, error);
+      g_error_free (error);
+      return;
+    }
+
+  aliases = g_array_sized_new (TRUE, FALSE, sizeof (gchar *), contacts->len);
+
+  for (i = 0; i < contacts->len; i++)
+    {
+      TpHandle handle;
+      gchar *alias;
+
+      handle = g_array_index (contacts, TpHandle, i);
+
+      alias = conn_get_alias (self, contact_handles, handle);
+
+      g_array_append_val (aliases, alias);
+    }
+
+  res = (gchar **) g_array_free (aliases, FALSE);
+
+  tp_svc_connection_interface_aliasing_return_from_request_aliases (
+      context, (const gchar **) res);
+
+  g_strfreev (res);
+}
+
+static void
+tpsip_connection_get_aliases (TpSvcConnectionInterfaceAliasing *iface,
+                              const GArray *contacts,
+                              DBusGMethodInvocation *context)
+{
+  TpsipConnection *self = TPSIP_CONNECTION (iface);
+  TpBaseConnection *base = (TpBaseConnection *) self;
+  TpHandleRepoIface *contact_handles;
+  GHashTable *result;
+  GError *error = NULL;
+  guint i;
+
+  TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
+
+  contact_handles = tp_base_connection_get_handles (base,
+      TP_HANDLE_TYPE_CONTACT);
+
+  if (!tp_handles_are_valid (contact_handles, contacts, FALSE, &error))
+    {
+      dbus_g_method_return_error (context, error);
+      g_error_free (error);
+      return;
+    }
+
+  result = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+      NULL, g_free);
+
+  for (i = 0; i < contacts->len; i++)
+    {
+      TpHandle handle;
+      gchar *alias;
+
+      handle = g_array_index (contacts, TpHandle, i);
+
+      alias = conn_get_alias (self, contact_handles, handle);
+
+      g_hash_table_insert (result, GUINT_TO_POINTER (handle), alias);
+    }
+
+  tp_svc_connection_interface_aliasing_return_from_get_aliases (context,
+      result);
+
+  g_hash_table_destroy (result);
+}
+
+static void
+emit_self_alias_change (TpsipConnection *self, const gchar *alias)
+{
+  TpBaseConnection *base = (TpBaseConnection *) self;
+  GPtrArray *change_data;
+  GValue change_pair;
+
+  g_value_init (&change_pair, TP_STRUCT_TYPE_ALIAS_PAIR);
+  g_value_take_boxed (&change_pair,
+      dbus_g_type_specialized_construct (TP_STRUCT_TYPE_ALIAS_PAIR));
+  dbus_g_type_struct_set (&change_pair,
+      0, base->self_handle,
+      1, alias,
+      G_MAXUINT);
+  change_data = g_ptr_array_sized_new (1);
+  g_ptr_array_add (change_data, g_value_get_boxed (&change_pair));
+
+  tp_svc_connection_interface_aliasing_emit_aliases_changed (self, change_data);
+
+  g_ptr_array_free (change_data, TRUE);
+  g_value_unset (&change_pair);
+}
+
+static void
+tpsip_connection_set_aliases (TpSvcConnectionInterfaceAliasing *iface,
+                              GHashTable *aliases,
+                              DBusGMethodInvocation *context)
+{
+  TpsipConnection *self = TPSIP_CONNECTION (iface);
+  TpBaseConnection *base = (TpBaseConnection *) self;
+  const gchar *alias;
+
+  TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
+
+  /* We only care about the self alias */
+  alias = g_hash_table_lookup (aliases, GINT_TO_POINTER (base->self_handle));
+
+  if (alias == NULL || g_hash_table_size (aliases) > 1)
+    {
+      /* One of the handles (if there are any) cannot be the self handle */
+      GError err = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+          "Cannot set aliases for any contact except self" };
+      dbus_g_method_return_error (context, &err);
+      return;
+    }
+
+  DEBUG("setting alias for self: %s", alias);
+  g_object_set (self, "alias", alias, NULL);
+
+  emit_self_alias_change (self, alias);
+
+  tp_svc_connection_interface_aliasing_return_from_set_aliases (context);
+}
+
+static void
+tpsip_conn_aliasing_fill_contact_attributes (GObject *obj,
+    const GArray *contacts, GHashTable *attributes_hash)
+{
+  TpsipConnection *self = TPSIP_CONNECTION (obj);
+  TpBaseConnection *base = (TpBaseConnection *) self;
+  TpHandleRepoIface *contact_handles;
+  guint i;
+
+  contact_handles = tp_base_connection_get_handles (base,
+      TP_HANDLE_TYPE_CONTACT);
+
+  for (i = 0; i < contacts->len; i++)
+    {
+      TpHandle handle;
+      GValue *val;
+
+      handle = g_array_index (contacts, TpHandle, i);
+
+      val = tp_g_value_slice_new (G_TYPE_STRING);
+
+      g_value_take_string (val,
+          conn_get_alias (self, contact_handles, handle));
+
+      tp_contacts_mixin_set_contact_attribute (attributes_hash, handle,
+          TP_IFACE_CONNECTION_INTERFACE_ALIASING "/alias", val);
+    }
+}
+
+void
+tpsip_conn_aliasing_init (TpsipConnection *conn)
+{
+  tp_contacts_mixin_add_contact_attributes_iface (G_OBJECT (conn),
+      TP_IFACE_CONNECTION_INTERFACE_ALIASING,
+      tpsip_conn_aliasing_fill_contact_attributes);
+}
+
+void
+tpsip_conn_aliasing_iface_init (gpointer g_iface, gpointer iface_data)
+{
+  TpSvcConnectionInterfaceAliasingClass *klass =
+    (TpSvcConnectionInterfaceAliasingClass *) g_iface;
+
+#define IMPLEMENT(x) tp_svc_connection_interface_aliasing_implement_##x (\
+    klass, tpsip_connection_##x)
+  IMPLEMENT(get_alias_flags);
+  IMPLEMENT(request_aliases);
+  IMPLEMENT(get_aliases);
+  IMPLEMENT(set_aliases);
+#undef IMPLEMENT
+}
diff --git a/src/conn-aliasing.h b/src/conn-aliasing.h
new file mode 100644
index 0000000..953ba0a
--- /dev/null
+++ b/src/conn-aliasing.h
@@ -0,0 +1,33 @@
+/*
+ * conn-aliasing.h - Aliasing interface implementation for TpsipConnection
+ * Copyright (C) 2008 Nokia Corporation
+ *   @author Mikhail Zabaluev <mikhail.zabaluev at nokia.com>
+ *
+ * This work 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 work 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 work; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __TPSIP_CONN_ALIASING_H__
+#define __TPSIP_CONN_ALIASING_H__
+
+#include "sip-connection.h"
+
+G_BEGIN_DECLS
+
+void tpsip_conn_aliasing_init (TpsipConnection *conn);
+void tpsip_conn_aliasing_iface_init (gpointer g_iface, gpointer iface_data);
+
+G_END_DECLS
+
+#endif /*__TPSIP_CONN_ALIASING_H__*/
diff --git a/src/sip-connection-helpers.c b/src/sip-connection-helpers.c
index 7889e5a..e61f985 100644
--- a/src/sip-connection-helpers.c
+++ b/src/sip-connection-helpers.c
@@ -804,3 +804,50 @@ error:
   su_home_deinit (home);
   return retval;
 }
+
+static GQuark
+tpsip_handle_url_quark ()
+{
+  static GQuark quark = 0;
+
+  if (G_UNLIKELY (quark == 0))
+    quark = g_quark_from_static_string ("tpsip-handle-url");
+
+  return quark;
+}
+
+const url_t*
+tpsip_conn_get_contact_url (TpsipConnection *self,
+                            TpHandle handle)
+{
+  TpBaseConnection *base = (TpBaseConnection *) self;
+  TpsipConnectionPrivate *priv = TPSIP_CONNECTION_GET_PRIVATE (self);
+  TpHandleRepoIface *contact_handles;
+  GQuark url_quark;
+  url_t *url;
+  GError *error;
+
+  contact_handles = tp_base_connection_get_handles (base,
+      TP_HANDLE_TYPE_CONTACT);
+
+  if (!tp_handle_is_valid (contact_handles, handle, &error))
+    {
+      DEBUG("invalid handle %u: %s", handle, error->message);
+      g_error_free (error);
+      return NULL;
+    }
+
+  url_quark = tpsip_handle_url_quark ();
+
+  url = tp_handle_get_qdata (contact_handles, handle, url_quark);
+
+  if (url == NULL)
+    {
+      url = url_make (priv->sofia_home,
+          tp_handle_inspect (contact_handles, handle));
+
+      tp_handle_set_qdata (contact_handles, handle, url_quark, url, NULL);
+    }
+
+  return url;
+}
diff --git a/src/sip-connection-helpers.h b/src/sip-connection-helpers.h
index 3a27201..ad85c08 100644
--- a/src/sip-connection-helpers.h
+++ b/src/sip-connection-helpers.h
@@ -58,7 +58,7 @@ void tpsip_conn_save_event (TpsipConnection *conn,
                             nua_saved_event_t ret_saved [1]);
 
 /***********************************************************************
- * SIP URI helpers *
+ * SIP URI helpers
  ***********************************************************************/
 
 gchar * tpsip_handle_normalize (TpHandleRepoIface *repo,
@@ -66,8 +66,8 @@ gchar * tpsip_handle_normalize (TpHandleRepoIface *repo,
                                 gpointer context,
                                 GError **error);
 
-const url_t* tpsip_handle_inspect_url (TpHandleRepoIface *repo,
-                                       TpHandle handle);
+const url_t* tpsip_conn_get_contact_url (TpsipConnection *conn,
+                                         TpHandle handle);
 
 G_END_DECLS
 
diff --git a/src/sip-connection-private.h b/src/sip-connection-private.h
index 9ab97cd..2362927 100644
--- a/src/sip-connection-private.h
+++ b/src/sip-connection-private.h
@@ -48,6 +48,7 @@ struct _TpsipConnectionPrivate
   gchar *address;
   gchar *auth_user;
   gchar *password;
+  gchar *alias;
   gchar *transport;
   TpsipConnectionKeepaliveMechanism keepalive_mechanism;
   gint keepalive_interval;
diff --git a/src/sip-connection.c b/src/sip-connection.c
index 9fef8be..ffb1a56 100644
--- a/src/sip-connection.c
+++ b/src/sip-connection.c
@@ -40,6 +40,8 @@
 #include "media-factory.h"
 #include "text-factory.h"
 
+#include "conn-aliasing.h"
+
 #include "sip-connection-enumtypes.h"
 #include "sip-connection-helpers.h"
 #include "sip-connection-private.h"
@@ -61,6 +63,8 @@ G_DEFINE_TYPE_WITH_CODE(TpsipConnection, tpsip_connection,
         tp_dbus_properties_mixin_iface_init);
     G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACTS,
         tp_contacts_mixin_iface_init);
+    G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING,
+        tpsip_conn_aliasing_iface_init);
     G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION, conn_iface_init))
 
 #define ERROR_IF_NOT_CONNECTED_ASYNC(BASE, CONTEXT) \
@@ -80,6 +84,7 @@ enum
   PROP_ADDRESS = 1,      /**< public SIP address (SIP URI) */
   PROP_AUTH_USER,        /**< account username (if different from public address userinfo part) */
   PROP_PASSWORD,         /**< account password (for registration) */
+  PROP_ALIAS,               /* Display name for self */
 
   PROP_TRANSPORT,        /**< outbound transport */
   PROP_PROXY,            /**< outbound SIP proxy (SIP URI) */
@@ -151,17 +156,14 @@ priv_handle_parse_from (const sip_t *sip,
   return handle;
 }
 
-static gchar *normalize_sipuri (TpHandleRepoIface *repo, const gchar *sipuri,
-    gpointer context, GError **error);
-
 static void
 tpsip_create_handle_repos (TpBaseConnection *conn,
-                         TpHandleRepoIface *repos[NUM_TP_HANDLE_TYPES])
+                           TpHandleRepoIface *repos[NUM_TP_HANDLE_TYPES])
 {
   repos[TP_HANDLE_TYPE_CONTACT] =
       (TpHandleRepoIface *)g_object_new (TP_TYPE_DYNAMIC_HANDLE_REPO,
           "handle-type", TP_HANDLE_TYPE_CONTACT,
-          "normalize-function", normalize_sipuri,
+          "normalize-function", tpsip_handle_normalize,
           "default-normalize-context", conn,
           NULL);
 }
@@ -202,13 +204,15 @@ tpsip_connection_init (TpsipConnection *self)
       G_STRUCT_OFFSET (TpsipConnection, contacts));
 
   tp_base_connection_register_with_contacts_mixin ((TpBaseConnection *) self);
+
+  tpsip_conn_aliasing_init (self);
 }
 
 static void
 tpsip_connection_set_property (GObject      *object,
-                             guint         property_id,
-                             const GValue *value,
-                             GParamSpec   *pspec)
+                               guint         property_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
 {
   TpsipConnection *self = (TpsipConnection*) object;
   TpsipConnectionPrivate *priv = TPSIP_CONNECTION_GET_PRIVATE (self);
@@ -229,6 +233,11 @@ tpsip_connection_set_property (GObject      *object,
     priv->password = g_value_dup_string (value);
     break;
   }
+  case PROP_ALIAS: {
+    g_free(priv->alias);
+    priv->alias = g_value_dup_string (value);
+    break;
+  }
   case PROP_TRANSPORT: {
     g_free(priv->transport);
     priv->transport = g_value_dup_string (value);
@@ -332,14 +341,18 @@ tpsip_connection_get_property (GObject      *object,
     g_value_set_string (value, priv->auth_user);
     break;
   }
-  case PROP_TRANSPORT: {
-    g_value_set_string (value, priv->transport);
-    break;
-  }
   case PROP_PASSWORD: {
     g_value_set_string (value, priv->password);
     break;
   }
+  case PROP_ALIAS: {
+    g_value_set_string (value, priv->alias);
+    break;
+  }
+  case PROP_TRANSPORT: {
+    g_value_set_string (value, priv->transport);
+    break;
+  }
   case PROP_PROXY: {
     priv_value_set_url_as_string (value, priv->proxy_url);
     break;
@@ -418,6 +431,7 @@ tpsip_connection_class_init (TpsipConnectionClass *klass)
 {
   static const gchar *interfaces_always_present[] = {
       TP_IFACE_CONNECTION_INTERFACE_CONTACTS,
+      TP_IFACE_CONNECTION_INTERFACE_ALIASING,
       NULL };
 
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -470,6 +484,12 @@ tpsip_connection_class_init (TpsipConnectionClass *klass)
       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
   INST_PROP(PROP_PASSWORD);
 
+  param_spec = g_param_spec_string ("alias", "Alias",
+      "User's display name",
+      NULL,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  INST_PROP(PROP_ALIAS);
+
   param_spec = g_param_spec_string ("transport", "Transport protocol",
       "Preferred transport protocol (auto, udp, tcp)",
       NULL,
@@ -1015,6 +1035,7 @@ tpsip_connection_finalize (GObject *obj)
   g_free (priv->address);
   g_free (priv->auth_user);
   g_free (priv->password);
+  g_free (priv->alias);
   g_free (priv->transport);
   g_free (priv->stun_host);
   g_free (priv->local_ip_address);
@@ -1167,17 +1188,6 @@ tpsip_connection_disconnected (TpBaseConnection *base)
     }
 }
 
-static gchar *
-normalize_sipuri (TpHandleRepoIface *repo,
-                  const gchar *sipuri,
-                  gpointer context,
-                  GError **error)
-{
-    TpsipConnection *conn = TPSIP_CONNECTION (context);
-
-    return tpsip_conn_normalize_uri (conn, sipuri, error);
-}
-
 static void
 conn_iface_init(gpointer g_iface, gpointer iface_data)
 {
-- 
1.5.6.5




More information about the Telepathy-commits mailing list