[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