diff options
author | Pekka Pessi <Pekka.Pessi@nokia.com> | 2011-02-07 19:58:07 +0200 |
---|---|---|
committer | Pekka Pessi <Pekka.Pessi@nokia.com> | 2011-02-07 19:58:07 +0200 |
commit | 262656c55e4112d36005426cd5985df3c94a74f7 (patch) | |
tree | a9431f1236a8ace7f49273517f0f56162c55c7e8 | |
parent | 26eae76d331cfa19edfc35dabf258a353904bd2a (diff) | |
parent | 9b8b2a7a9d0a39557394c19d932603ac3a37dd40 (diff) |
Merge branch 'tpsip-base-connection'
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/conn-aliasing.h | 33 | ||||
-rw-r--r-- | src/media-factory.c | 28 | ||||
-rw-r--r-- | src/protocol.c | 1 | ||||
-rw-r--r-- | src/sip-connection-helpers.c | 306 | ||||
-rw-r--r-- | src/sip-connection-helpers.h | 27 | ||||
-rw-r--r-- | src/sip-connection-private.h | 1 | ||||
-rw-r--r-- | src/sip-connection-sofia.h | 48 | ||||
-rw-r--r-- | src/sip-connection.c | 107 | ||||
-rw-r--r-- | src/sip-connection.h | 17 | ||||
-rw-r--r-- | src/sip-media-channel.c | 15 | ||||
-rw-r--r-- | src/sip-media-session.c | 7 | ||||
-rw-r--r-- | src/sip-text-channel.c | 12 | ||||
-rw-r--r-- | src/text-factory.c | 31 | ||||
-rw-r--r-- | tests/twisted/Makefile.am | 3 | ||||
-rw-r--r-- | tests/twisted/test-self-alias.py | 10 | ||||
-rw-r--r-- | tpsip/Makefile.am | 9 | ||||
-rw-r--r-- | tpsip/base-connection-sofia.c (renamed from src/sip-connection-sofia.c) | 23 | ||||
-rw-r--r-- | tpsip/base-connection.c | 205 | ||||
-rw-r--r-- | tpsip/base-connection.h | 92 | ||||
-rw-r--r-- | tpsip/connection-aliasing.c (renamed from src/conn-aliasing.c) | 117 | ||||
-rw-r--r-- | tpsip/connection-aliasing.h | 58 | ||||
-rw-r--r-- | tpsip/handles.c | 345 | ||||
-rw-r--r-- | tpsip/handles.h | 47 | ||||
-rw-r--r-- | tpsip/sofia-decls.h | 9 |
25 files changed, 974 insertions, 583 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index ca15a87..a8c6c4e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -86,8 +86,6 @@ 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 \ @@ -98,9 +96,7 @@ libtpsip_convenience_la_SOURCES = \ text-factory.c \ sip-connection-helpers.h \ sip-connection-helpers.c \ - sip-connection-private.h \ - sip-connection-sofia.h \ - sip-connection-sofia.c + sip-connection-private.h nodist_libtpsip_convenience_la_SOURCES = \ $(BUILT_SOURCES) diff --git a/src/conn-aliasing.h b/src/conn-aliasing.h deleted file mode 100644 index 953ba0a..0000000 --- a/src/conn-aliasing.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * conn-aliasing.h - Aliasing interface implementation for TpsipConnection - * Copyright (C) 2008 Nokia Corporation - * @author Mikhail Zabaluev <mikhail.zabaluev@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/media-factory.c b/src/media-factory.c index 1e941fe..14e13b7 100644 --- a/src/media-factory.c +++ b/src/media-factory.c @@ -27,8 +27,8 @@ #include <telepathy-glib/interfaces.h> #include "sip-media-channel.h" -#include "sip-connection.h" -#include "sip-connection-helpers.h" +#include <tpsip/base-connection.h> +#include <tpsip/handles.h> #include <sofia-sip/sip_status.h> @@ -61,7 +61,7 @@ typedef struct _TpsipMediaFactoryPrivate TpsipMediaFactoryPrivate; struct _TpsipMediaFactoryPrivate { /* unreferenced (since it owns this factory) */ - TpsipConnection *conn; + TpBaseConnection *conn; /* array of referenced (TpsipMediaChannel *) */ GPtrArray *channels; /* for unique channel object paths, currently always increments */ @@ -181,9 +181,10 @@ tpsip_media_factory_class_init (TpsipMediaFactoryClass *klass) object_class->dispose = tpsip_media_factory_dispose; object_class->finalize = tpsip_media_factory_finalize; - param_spec = g_param_spec_object ("connection", "TpsipConnection object", + param_spec = g_param_spec_object ("connection", + "TpsipBaseConnection object", "SIP connection that owns this media channel factory", - TPSIP_TYPE_CONNECTION, + TPSIP_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); @@ -265,7 +266,6 @@ new_media_channel (TpsipMediaFactory *fac, { TpsipMediaFactoryPrivate *priv; TpsipMediaChannel *chan = NULL; - TpBaseConnection *conn; gchar *object_path; const gchar *nat_traversal = "none"; gboolean initial_audio; @@ -275,9 +275,8 @@ new_media_channel (TpsipMediaFactory *fac, g_assert (initiator != 0); priv = TPSIP_MEDIA_FACTORY_GET_PRIVATE (fac); - conn = (TpBaseConnection *)priv->conn; - object_path = g_strdup_printf ("%s/MediaChannel%u", conn->object_path, + object_path = g_strdup_printf ("%s/MediaChannel%u", priv->conn->object_path, priv->channel_index++); DEBUG("channel object path %s", object_path); @@ -285,7 +284,7 @@ new_media_channel (TpsipMediaFactory *fac, initial_audio = ((flags & TPSIP_MEDIA_CHANNEL_CREATE_WITH_AUDIO) != 0); initial_video = ((flags & TPSIP_MEDIA_CHANNEL_CREATE_WITH_VIDEO) != 0); - g_object_get (conn, + g_object_get (priv->conn, "immutable-streams", &immutable_streams, NULL); @@ -338,15 +337,12 @@ tpsip_nua_i_invite_cb (TpBaseConnection *conn, TpsipMediaFactory *fac) { TpsipMediaChannel *channel; - TpHandleRepoIface *contact_repo; TpHandle handle; guint channel_flags = 0; /* figure out a handle for the identity */ - contact_repo = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT); - - handle = tpsip_handle_parse_from (contact_repo, ev->sip); + handle = tpsip_handle_by_requestor (conn, ev->sip); if (!handle) { MESSAGE ("incoming INVITE with invalid sender information"); @@ -355,7 +351,7 @@ tpsip_nua_i_invite_cb (TpBaseConnection *conn, } DEBUG("Got incoming invite from <%s>", - tp_handle_inspect (contact_repo, handle)); + tpsip_handle_inspect (conn, handle)); if (handle == conn->self_handle) { @@ -366,7 +362,7 @@ tpsip_nua_i_invite_cb (TpBaseConnection *conn, channel = new_media_channel (fac, handle, handle, channel_flags); - tp_handle_unref (contact_repo, handle); + tpsip_handle_unref (conn, handle); /* We delay emission of NewChannel(s) until we have the data on * initial media */ @@ -379,7 +375,7 @@ tpsip_nua_i_invite_cb (TpBaseConnection *conn, } static void -connection_status_changed_cb (TpsipConnection *conn, +connection_status_changed_cb (TpsipBaseConnection *conn, guint status, guint reason, TpsipMediaFactory *self) diff --git a/src/protocol.c b/src/protocol.c index d9c2383..df9a890 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -26,6 +26,7 @@ #include <dbus/dbus-glib.h> #include <tpsip/sofia-decls.h> +#include <tpsip/handles.h> #include <sofia-sip/su_glib.h> #define DEBUG_FLAG TPSIP_DEBUG_CONNECTION diff --git a/src/sip-connection-helpers.c b/src/sip-connection-helpers.c index 8ad9b42..da192eb 100644 --- a/src/sip-connection-helpers.c +++ b/src/sip-connection-helpers.c @@ -31,6 +31,7 @@ #include <telepathy-glib/svc-connection.h> #include <tpsip/util.h> +#include <tpsip/handles.h> #include "sip-connection-helpers.h" @@ -63,7 +64,7 @@ priv_sip_to_url_make (TpsipConnection *conn, { const url_t *url; - url = tpsip_conn_get_contact_url (conn, contact); + url = tpsip_handle_inspect_uri (TP_BASE_CONNECTION (conn), contact); return sip_to_create (home, (const url_string_t *) url); } @@ -152,14 +153,6 @@ tpsip_conn_create_request_handle (TpsipConnection *conn, } void -tpsip_conn_save_event (TpsipConnection *conn, - nua_saved_event_t ret_saved [1]) -{ - TpsipConnectionPrivate *priv = TPSIP_CONNECTION_GET_PRIVATE (conn); - nua_save_event (priv->sofia_nua, ret_saved); -} - -void tpsip_conn_update_proxy_and_transport (TpsipConnection *conn) { TpsipConnectionPrivate *priv = TPSIP_CONNECTION_GET_PRIVATE (conn); @@ -528,13 +521,17 @@ tpsip_conn_resolv_stun_server (TpsipConnection *conn, const gchar *stun_host) tpsip_conn_set_stun_server_address (conn, stun_host); return; } - + if (NULL == priv->sofia_resolver) { - priv->sofia_resolver = - sres_resolver_create (priv->sofia_root, NULL, TAG_END()); + su_root_t *root = NULL; + + g_object_get (conn, "sofia-root", &root, NULL); + + priv->sofia_resolver = sres_resolver_create (root, NULL, TAG_END()); + + g_return_if_fail (priv->sofia_resolver != NULL); } - g_return_if_fail (priv->sofia_resolver != NULL); DEBUG("creating a new resolver query for STUN host name %s", stun_host); @@ -656,10 +653,13 @@ tpsip_conn_discover_stun_server (TpsipConnection *conn) if (NULL == priv->sofia_resolver) { - priv->sofia_resolver = - sres_resolver_create (priv->sofia_root, NULL, TAG_END()); + su_root_t *root = NULL; + + g_object_get (conn, "sofia-root", &root, NULL); + + priv->sofia_resolver = sres_resolver_create (root, NULL, TAG_END()); + g_return_if_fail (priv->sofia_resolver != NULL); } - g_return_if_fail (priv->sofia_resolver != NULL); DEBUG("creating a new STUN SRV query for domain %s", priv->account_url->url_host); @@ -674,208 +674,6 @@ tpsip_conn_discover_stun_server (TpsipConnection *conn) g_free (srv_domain); } -static gboolean -priv_is_host (const gchar* str) -{ - static GRegex *host_regex = NULL; - -#define DOMAIN "[a-z0-9]([-a-z0-9]*[a-z0-9])?" -#define TLD "[a-z]([-a-z0-9]*[a-z0-9])?" - - if (host_regex == NULL) - { - GError *error = NULL; - - host_regex = g_regex_new ("^(" - "("DOMAIN"\\.)*"TLD"\\.?|" /* host name */ - "[0-9]{1,3}(\\.[0-9]{1,3}){3}|" /* IPv4 address */ - "\\[[0-9a-f:.]\\]" /* IPv6 address, sloppily */ - ")$", - G_REGEX_CASELESS | G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &error); - - if (error != NULL) - g_error ("failed to compile the host regex: %s", error->message); - } - -#undef DOMAIN -#undef TLD - - return g_regex_match (host_regex, str, 0, NULL); -} - -static gboolean -priv_is_tel_num (const gchar *str) -{ - static GRegex *tel_num_regex = NULL; - - if (tel_num_regex == NULL) - { - GError *error = NULL; - - tel_num_regex = g_regex_new ( - "^\\s*[\\+(]?\\s*[0-9][-.0-9()\\s]*$", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &error); - - if (error != NULL) - g_error ("failed to compile the telephone number regex: %s", error->message); - } - - return g_regex_match (tel_num_regex, str, 0, NULL); -} - -/* Strip the non-essential characters from a string regarded as - * a telephone number */ -static gchar * -priv_strip_tel_num (const gchar *fuzzy) -{ - static GRegex *cruft_regex = NULL; - - if (cruft_regex == NULL) - { - GError *error = NULL; - - cruft_regex = g_regex_new ("[^+0-9]+", - G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &error); - - if (error != NULL) - g_error ("failed to compile the non-essential telephone number cruft regex: %s", error->message); - } - - return g_regex_replace_literal (cruft_regex, fuzzy, -1, 0, "", 0, NULL); -} - -static const char * -priv_lowercase_url_part (su_home_t *home, const char *src) -{ - size_t n = 0; - size_t i; - char *res; - - for (i = 0; src[i]; i++) - { - if (g_ascii_isupper (src[i])) - { - n = i + strlen (src + i); - break; - } - } - - if (!src[i]) - return src; - - res = su_alloc (home, n + 1); - memcpy (res, src, i); - for (; i < n; i++) - res[i] = g_ascii_tolower (src[i]); - res[i] = '\0'; - - return (const char *) res; -} - -#define TPSIP_RESERVED_CHARS_ALLOWED_IN_USERNAME "!*'()&=+$,;?/" - -gchar * -tpsip_normalize_contact (const gchar *sipuri, - const url_t *base_url, - const gchar *transport, - GError **error) -{ - su_home_t home[1] = { SU_HOME_INIT(home) }; - url_t *url; - gchar *retval = NULL; - char *c; - - url = url_make (home, sipuri); - - if (url == NULL || - (url->url_scheme == NULL && url->url_user == NULL)) - { - /* we got username or phone number, local to our domain */ - gchar *user; - - if (base_url == NULL || base_url->url_host == NULL) - { - WARNING ("bare name given, but no account URL is set"); - goto error; - } - - if (priv_is_tel_num (sipuri)) - { - user = priv_strip_tel_num (sipuri); - } - else - { - user = g_uri_escape_string (sipuri, - TPSIP_RESERVED_CHARS_ALLOWED_IN_USERNAME, FALSE); - } - - if (base_url->url_type == url_sips) - url = url_format (home, "sips:%s@%s", - user, base_url->url_host); - else - url = url_format (home, "sip:%s@%s", - user, base_url->url_host); - - g_free (user); - - if (!url) goto error; - } - else if (url->url_scheme == NULL) - { - /* Set the scheme to SIP or SIPS accordingly to the connection's - * transport preference */ - if (transport != NULL - && g_ascii_strcasecmp (transport, "tls") == 0) - { - url->url_type = url_sips; - url->url_scheme = "sips"; - } - else - { - url->url_type = url_sip; - url->url_scheme = "sip"; - } - } - - if (url_sanitize (url) != 0) goto error; - - /* scheme should've been set by now */ - if (url->url_scheme == NULL || (url->url_scheme[0] == 0)) - goto error; - - /* convert the scheme to lowercase */ - /* Note: we can't do it in place because url->url_scheme may point to - * a static string */ - url->url_scheme = priv_lowercase_url_part (home, url->url_scheme); - - /* Check that if we have '@', the username isn't empty. - * Note that we rely on Sofia-SIP to canonize the user name */ - if (url->url_user) - { - if (url->url_user[0] == 0) goto error; - } - - /* host should be set and valid */ - if (url->url_host == NULL || !priv_is_host (url->url_host)) - goto error; - - /* convert host to lowercase */ - for (c = (char *) url->url_host; *c; c++) - { - *c = g_ascii_tolower (*c); - } - - retval = g_strdup (url_as_string (home, url)); - -error: - if (retval == NULL) - g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_HANDLE, - "invalid SIP URI"); - - su_home_deinit (home); - return retval; -} - gchar * tpsip_handle_normalize (TpHandleRepoIface *repo, const gchar *sipuri, @@ -889,78 +687,6 @@ tpsip_handle_normalize (TpHandleRepoIface *repo, error); } -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; -} - -TpHandle -tpsip_handle_parse_from (TpHandleRepoIface *contact_repo, - const sip_t *sip) -{ - TpHandle handle = 0; - gchar *url_str; - - g_return_val_if_fail (sip != NULL, 0); - - if (sip->sip_from) - { - su_home_t tmphome[1] = { SU_HOME_INIT(tmphome) }; - - url_str = url_as_string (tmphome, sip->sip_from->a_url); - - handle = tp_handle_ensure (contact_repo, url_str, NULL, NULL); - - /* TODO: set qdata for the display name */ - - su_home_deinit (tmphome); - } - - return handle; -} - #ifdef HAVE_LIBIPHB static int diff --git a/src/sip-connection-helpers.h b/src/sip-connection-helpers.h index 4644908..97896b9 100644 --- a/src/sip-connection-helpers.h +++ b/src/sip-connection-helpers.h @@ -51,33 +51,6 @@ void tpsip_conn_resolv_stun_server (TpsipConnection *conn, const gchar *stun_hos void tpsip_conn_discover_stun_server (TpsipConnection *conn); /*********************************************************************** - * Functions for saving NUA events - ***********************************************************************/ - -void tpsip_conn_save_event (TpsipConnection *conn, - nua_saved_event_t ret_saved [1]); - -/*********************************************************************** - * SIP URI helpers - ***********************************************************************/ - -gchar * tpsip_handle_normalize (TpHandleRepoIface *repo, - const gchar *sipuri, - gpointer context, - GError **error); - -gchar *tpsip_normalize_contact (const gchar *sipuri, - const url_t *base_url, - const gchar *transport, - GError **error); - -const url_t* tpsip_conn_get_contact_url (TpsipConnection *conn, - TpHandle handle); - -TpHandle tpsip_handle_parse_from (TpHandleRepoIface *contact_repo, - const sip_t *sip); - -/*********************************************************************** * Heartbeat management for keepalives ***********************************************************************/ diff --git a/src/sip-connection-private.h b/src/sip-connection-private.h index 2250694..c312109 100644 --- a/src/sip-connection-private.h +++ b/src/sip-connection-private.h @@ -35,7 +35,6 @@ struct _TpsipConnectionPrivate { - su_root_t *sofia_root; nua_t *sofia_nua; su_home_t *sofia_home; nua_handle_t *register_op; diff --git a/src/sip-connection-sofia.h b/src/sip-connection-sofia.h deleted file mode 100644 index a56b1cb..0000000 --- a/src/sip-connection-sofia.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * sip-connection-sofia.h - Header for TpsipConnection Sofia event handling - * Copyright (C) 2006-2008 Nokia Corporation - * @author Kai Vehmanen <first.surname@nokia.com> - * @author Mikhail Zabaluev <mikhail.zabaluev@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_CONNECTION_SOFIA_H__ -#define __TPSIP_CONNECTION_SOFIA_H__ - -#include <tpsip/sofia-decls.h> -#include <tpsip/event-target.h> -#include "sip-connection.h" - -G_BEGIN_DECLS - -/** - * Callback for events delivered by the SIP stack. - * - * See libsofia-sip-ua/nua/nua.h documentation. - */ -void tpsip_connection_sofia_callback (nua_event_t event, - int status, - char const *phrase, - nua_t *nua, - TpsipConnection *conn, - nua_handle_t *nh, - TpsipEventTarget *target, - sip_t const *sip, - tagi_t tags[]); - -G_END_DECLS - -#endif /* #ifndef __TPSIP_CONNECTION_SOFIA_H__*/ diff --git a/src/sip-connection.c b/src/sip-connection.c index b515699..2751a44 100644 --- a/src/sip-connection.c +++ b/src/sip-connection.c @@ -36,46 +36,30 @@ #include <telepathy-glib/svc-generic.h> #include <tpsip/event-target.h> +#include <tpsip/handles.h> +#include <tpsip/connection-aliasing.h> #include "sip-connection.h" #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" -#include "sip-connection-sofia.h" #include <sofia-sip/msg_header.h> #define DEBUG_FLAG TPSIP_DEBUG_CONNECTION #include "debug.h" -static void event_target_iface_init (gpointer, gpointer); -static void conn_iface_init (gpointer, gpointer); - -G_DEFINE_TYPE_WITH_CODE(TpsipConnection, tpsip_connection, - TP_TYPE_BASE_CONNECTION, - G_IMPLEMENT_INTERFACE (TPSIP_TYPE_EVENT_TARGET, event_target_iface_init); +G_DEFINE_TYPE_WITH_CODE (TpsipConnection, tpsip_connection, + TPSIP_TYPE_BASE_CONNECTION, G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_DBUS_PROPERTIES, 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) \ - if ((BASE)->status != TP_CONNECTION_STATUS_CONNECTED) \ - { \ - GError e = { TP_ERRORS, TP_ERROR_NOT_AVAILABLE, \ - "Connection is disconnected" }; \ - DEBUG ("rejected request as disconnected"); \ - dbus_g_method_return_error ((CONTEXT), &e); \ - return; \ - } + tpsip_connection_aliasing_svc_iface_init); + G_IMPLEMENT_INTERFACE (TPSIP_TYPE_CONNECTION_ALIASING, NULL); +); /* properties */ @@ -102,7 +86,7 @@ enum PROP_LOCAL_PORT, /**< Local port for SIP (normally not needed, chosen by stack) */ PROP_EXTRA_AUTH_USER, /**< User name to use for extra authentication challenges */ PROP_EXTRA_AUTH_PASSWORD,/**< Password to use for extra authentication challenges */ - PROP_SOFIA_ROOT, /**< Event root pointer from the Sofia-SIP stack */ + PROP_SOFIA_NUA, /**< Base class accessing nua_t */ LAST_PROPERTY }; @@ -174,12 +158,7 @@ tpsip_connection_init (TpsipConnection *self) priv->sofia_home = su_home_new(sizeof (su_home_t)); - tp_contacts_mixin_init ((GObject *) self, - G_STRUCT_OFFSET (TpsipConnection, contacts)); - - tp_base_connection_register_with_contacts_mixin ((TpBaseConnection *) self); - - tpsip_conn_aliasing_init (self); + tpsip_connection_aliasing_init (self); } static void @@ -307,10 +286,6 @@ tpsip_connection_set_property (GObject *object, priv->extra_auth_password = g_value_dup_string (value); break; } - case PROP_SOFIA_ROOT: { - priv->sofia_root = g_value_get_pointer (value); - break; - } default: /* We don't have any other property... */ G_OBJECT_WARN_INVALID_PROPERTY_ID(object,property_id,pspec); @@ -396,8 +371,8 @@ tpsip_connection_get_property (GObject *object, g_value_set_uint (value, priv->local_port); break; } - case PROP_SOFIA_ROOT: { - g_value_set_pointer (value, priv->sofia_root); + case PROP_SOFIA_NUA: { + g_value_set_pointer (value, priv->sofia_nua); break; } default: @@ -439,15 +414,23 @@ tpsip_connection_get_implemented_interfaces (void) return interfaces_always_present; } +static nua_handle_t *tpsip_connection_create_nua_handle (TpsipBaseConnection *, + TpHandle); +static void tpsip_connection_add_auth_handler (TpsipBaseConnection *, + TpsipEventTarget *); + static void tpsip_connection_class_init (TpsipConnectionClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - TpBaseConnectionClass *base_class = - (TpBaseConnectionClass *)klass; + TpBaseConnectionClass *base_class = TP_BASE_CONNECTION_CLASS (klass); + TpsipBaseConnectionClass *sip_class = TPSIP_BASE_CONNECTION_CLASS (klass); GParamSpec *param_spec; /* Implement pure-virtual methods */ + sip_class->create_handle = tpsip_connection_create_nua_handle; + sip_class->add_auth_handler = tpsip_connection_add_auth_handler; + base_class->create_handle_repos = tpsip_create_handle_repos; base_class->get_unique_connection_name = tpsip_connection_unique_name; base_class->create_channel_managers = @@ -469,10 +452,7 @@ tpsip_connection_class_init (TpsipConnectionClass *klass) #define INST_PROP(x) \ g_object_class_install_property (object_class, x, param_spec) - param_spec = g_param_spec_pointer ("sofia-root", "Sofia root", - "Event root from Sofia-SIP stack", - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - INST_PROP(PROP_SOFIA_ROOT); + g_object_class_override_property (object_class, PROP_SOFIA_NUA, "sofia-nua"); param_spec = g_param_spec_string ("address", "SIP address", "SIP AoR URI", @@ -493,11 +473,7 @@ 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); + g_object_class_override_property (object_class, PROP_ALIAS, "alias"); param_spec = g_param_spec_string ("transport", "Transport protocol", "Preferred transport protocol (auto, udp, tcp)", @@ -599,9 +575,6 @@ tpsip_connection_class_init (TpsipConnectionClass *klass) tp_dbus_properties_mixin_class_init (object_class, G_STRUCT_OFFSET (TpsipConnectionClass, properties_class)); - - tp_contacts_mixin_class_init (object_class, - G_STRUCT_OFFSET (TpsipConnectionClass, contacts_class)); } typedef struct { @@ -855,9 +828,9 @@ tpsip_connection_auth_cb (TpsipEventTarget *target, FALSE); } -void -tpsip_connection_connect_auth_handler (TpsipConnection *self, - TpsipEventTarget *target) +static void +tpsip_connection_add_auth_handler (TpsipBaseConnection *self, + TpsipEventTarget *target) { g_signal_connect_object (target, "nua-event", @@ -866,6 +839,12 @@ tpsip_connection_connect_auth_handler (TpsipConnection *self, 0); } +static nua_handle_t * +tpsip_connection_create_nua_handle (TpsipBaseConnection *base, TpHandle handle) +{ + return tpsip_conn_create_request_handle (TPSIP_CONNECTION (base), handle); +} + static gboolean tpsip_connection_nua_r_register_cb (TpsipConnection *self, const TpsipNuaEvent *ev, @@ -1014,11 +993,13 @@ tpsip_connection_start_connecting (TpBaseConnection *base, TpHandleRepoIface *contact_repo; const gchar *sip_address; const url_t *local_url; + su_root_t *root = NULL; g_assert (base->status == TP_INTERNAL_CONNECTION_STATUS_NEW); /* the construct parameters will be non-empty */ - g_assert (priv->sofia_root != NULL); + g_object_get (self, "sofia-root", &root, NULL); + g_assert (root != NULL); g_return_val_if_fail (priv->address != NULL, FALSE); contact_repo = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); @@ -1033,7 +1014,7 @@ tpsip_connection_start_connecting (TpBaseConnection *base, DEBUG("self_handle = %d, sip_address = %s", base->self_handle, sip_address); - priv->account_url = tpsip_conn_get_contact_url (self, base->self_handle); + priv->account_url = tpsip_handle_inspect_uri (base, base->self_handle); if (priv->account_url == NULL) { g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE, @@ -1044,9 +1025,9 @@ tpsip_connection_start_connecting (TpBaseConnection *base, local_url = tpsip_conn_get_local_url (self); /* step: create stack instance */ - priv->sofia_nua = nua_create (priv->sofia_root, - tpsip_connection_sofia_callback, - self, + priv->sofia_nua = nua_create (root, + tpsip_base_connection_sofia_callback, + TPSIP_BASE_CONNECTION (self), SOATAG_AF(SOA_AF_IP4_IP6), SIPTAG_FROM_STR(sip_address), NUTAG_URL(local_url), @@ -1131,13 +1112,3 @@ tpsip_connection_disconnected (TpBaseConnection *base) priv->register_op = NULL; } } - -static void -conn_iface_init(gpointer g_iface, gpointer iface_data) -{ -} - -static void -event_target_iface_init (gpointer g_iface, gpointer iface_data) -{ -} diff --git a/src/sip-connection.h b/src/sip-connection.h index 2280be9..dffbf6f 100644 --- a/src/sip-connection.h +++ b/src/sip-connection.h @@ -23,20 +23,11 @@ #include <glib-object.h> -#include <telepathy-glib/base-connection.h> -#include <telepathy-glib/contacts-mixin.h> +#include <tpsip/base-connection.h> #include <telepathy-glib/dbus-properties-mixin.h> -#include <tpsip/event-target.h> - - G_BEGIN_DECLS -#define TPSIP_DEFAULT_STUN_PORT 3478 - -/* Maximum defer timeout for deferrable Sofia timers */ -#define TPSIP_DEFER_TIMEOUT 30 - typedef enum { TPSIP_CONNECTION_KEEPALIVE_AUTO = 0, /** Keepalive management is up to the implementation */ @@ -51,14 +42,12 @@ typedef struct _TpsipConnectionClass TpsipConnectionClass; typedef struct _TpsipConnectionPrivate TpsipConnectionPrivate; struct _TpsipConnectionClass { - TpBaseConnectionClass parent_class; + TpsipBaseConnectionClass parent_class; TpDBusPropertiesMixinClass properties_class; - TpContactsMixinClass contacts_class; }; struct _TpsipConnection { - TpBaseConnection parent; - TpContactsMixin contacts; + TpsipBaseConnection parent; }; /* TYPE MACROS */ diff --git a/src/sip-media-channel.c b/src/sip-media-channel.c index b78a57f..cf07564 100644 --- a/src/sip-media-channel.c +++ b/src/sip-media-channel.c @@ -39,8 +39,9 @@ #define DEBUG_FLAG TPSIP_DEBUG_MEDIA #include "debug.h" -#include "sip-connection.h" -#include "sip-connection-helpers.h" + +#include <tpsip/base-connection.h> + #include "sip-media-session.h" #define TPSIP_CHANNEL_CALL_STATE_PROCEEDING_MASK \ @@ -145,7 +146,7 @@ typedef struct _TpsipMediaChannelPrivate TpsipMediaChannelPrivate; struct _TpsipMediaChannelPrivate { - TpsipConnection *conn; + TpsipBaseConnection *conn; TpsipMediaSession *session; gchar *object_path; TpHandle handle; @@ -322,7 +323,7 @@ tpsip_media_channel_class_init (TpsipMediaChannelClass *klass) param_spec = g_param_spec_object ("connection", "TpsipConnection object", "SIP connection object that owns this SIP media channel object.", - TPSIP_TYPE_CONNECTION, + TPSIP_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); @@ -580,7 +581,7 @@ tpsip_media_channel_set_property (GObject *object, * meaningfully changable on this channel, so we do nothing */ break; case PROP_CONNECTION: - priv->conn = TPSIP_CONNECTION (g_value_dup_object (value)); + priv->conn = g_value_dup_object (value); break; case PROP_OBJECT_PATH: g_free (priv->object_path); @@ -1578,7 +1579,7 @@ tpsip_media_channel_attach_to_nua_handle (TpsipMediaChannel *self, /* have the connection handle authentication, before all other * response callbacks */ - tpsip_connection_connect_auth_handler (priv->conn, TPSIP_EVENT_TARGET (self)); + tpsip_base_connection_add_auth_handler (priv->conn, TPSIP_EVENT_TARGET (self)); g_signal_connect (self, "nua-event::nua_i_invite", @@ -1704,7 +1705,7 @@ priv_outbound_call (TpsipMediaChannel *channel, { DEBUG("making outbound call - setting peer handle to %u", peer); - nh = tpsip_conn_create_request_handle (priv->conn, peer); + nh = tpsip_base_connection_create_handle (priv->conn, peer); priv_create_session (channel, nh, peer); /* Bind the channel object to the handle to handle NUA events */ diff --git a/src/sip-media-session.c b/src/sip-media-session.c index 8272200..988a990 100644 --- a/src/sip-media-session.c +++ b/src/sip-media-session.c @@ -38,10 +38,11 @@ #include "config.h" +#include <tpsip/base-connection.h> + #include "sip-media-session.h" #include "sip-media-channel.h" #include "sip-media-stream.h" -#include "sip-connection-helpers.h" #include "signals-marshal.h" #define DEBUG_FLAG TPSIP_DEBUG_MEDIA @@ -1022,7 +1023,7 @@ static void priv_save_event (TpsipMediaSession *self) { TpsipMediaSessionPrivate *priv = TPSIP_MEDIA_SESSION_GET_PRIVATE (self); - TpsipConnection *conn = NULL; + TpsipBaseConnection *conn = NULL; priv_zap_event (self); @@ -1030,7 +1031,7 @@ priv_save_event (TpsipMediaSession *self) g_return_if_fail (conn != NULL); - tpsip_conn_save_event (conn, priv->saved_event); + tpsip_base_connection_save_event (conn, priv->saved_event); g_object_unref (conn); diff --git a/src/sip-text-channel.c b/src/sip-text-channel.c index aeb0209..71be195 100644 --- a/src/sip-text-channel.c +++ b/src/sip-text-channel.c @@ -39,9 +39,7 @@ #include <telepathy-glib/svc-generic.h> #include <tpsip/event-target.h> - -#include "sip-connection.h" -#include "sip-connection-helpers.h" +#include <tpsip/base-connection.h> #include <sofia-sip/sip_protos.h> #include <sofia-sip/sip_status.h> @@ -112,7 +110,7 @@ typedef struct _TpsipTextChannelPrivate TpsipTextChannelPrivate; struct _TpsipTextChannelPrivate { - TpsipConnection *conn; + TpsipBaseConnection *conn; gchar *object_path; TpHandle handle; TpHandle initiator; @@ -186,7 +184,7 @@ tpsip_text_channel_constructed (GObject *obj) g_assert (priv->initiator != 0); tp_handle_ref (contact_handles, priv->initiator); - tpsip_connection_connect_auth_handler (priv->conn, TPSIP_EVENT_TARGET (obj)); + tpsip_base_connection_add_auth_handler (priv->conn, TPSIP_EVENT_TARGET (obj)); g_signal_connect (obj, "nua-event::nua_r_message", @@ -271,7 +269,7 @@ tpsip_text_channel_class_init(TpsipTextChannelClass *klass) param_spec = g_param_spec_object("connection", "TpsipConnection object", "SIP connection object that owns this SIP media channel object.", - TPSIP_TYPE_CONNECTION, + TPSIP_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); @@ -690,7 +688,7 @@ tpsip_text_channel_send_message (GObject *object, /* Okay, it's valid. Let's send it. */ - msg_nh = tpsip_conn_create_request_handle (priv->conn, priv->handle); + msg_nh = tpsip_base_connection_create_handle (priv->conn, priv->handle); if (msg_nh == NULL) { g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE, diff --git a/src/text-factory.c b/src/text-factory.c index d62b2b6..4b8d0b3 100644 --- a/src/text-factory.c +++ b/src/text-factory.c @@ -27,8 +27,8 @@ #include <telepathy-glib/interfaces.h> #include "sip-text-channel.h" -#include "sip-connection.h" -#include "sip-connection-helpers.h" +#include "tpsip/base-connection.h" +#include "tpsip/handles.h" #include <sofia-sip/msg_header.h> #include <sofia-sip/sip_tag.h> @@ -39,7 +39,7 @@ static void channel_manager_iface_init (gpointer g_iface, gpointer iface_data); -static void connection_status_changed_cb (TpsipConnection *conn, +static void connection_status_changed_cb (TpBaseConnection *conn, guint status, guint reason, TpsipTextFactory *self); static void tpsip_text_factory_close_all (TpsipTextFactory *self); @@ -57,7 +57,7 @@ enum typedef struct _TpsipTextFactoryPrivate TpsipTextFactoryPrivate; struct _TpsipTextFactoryPrivate { - TpsipConnection *conn; + TpBaseConnection *conn; /* guint handle => TpsipTextChannel *channel */ GHashTable *channels; @@ -144,7 +144,7 @@ tpsip_text_factory_set_property (GObject *object, switch (property_id) { case PROP_CONNECTION: - priv->conn = g_value_get_object (value); + priv->conn = TP_BASE_CONNECTION (g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -165,9 +165,10 @@ tpsip_text_factory_class_init (TpsipTextFactoryClass *klass) object_class->set_property = tpsip_text_factory_set_property; object_class->dispose = tpsip_text_factory_dispose; - param_spec = g_param_spec_object ("connection", "TpsipConnection object", + param_spec = g_param_spec_object ("connection", + "TpsipBaseConnection object", "SIP connection that owns this text channel factory", - TPSIP_TYPE_CONNECTION, + TPSIP_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); } @@ -281,7 +282,7 @@ tpsip_text_factory_new_channel (TpsipTextFactory *fac, GSList *request_tokens; priv = TPSIP_TEXT_FACTORY_GET_PRIVATE (fac); - conn = (TpBaseConnection *)(priv->conn); + conn = priv->conn; object_path = g_strdup_printf ("%s/TextChannel%u", conn->object_path, handle); @@ -463,7 +464,6 @@ tpsip_nua_i_message_cb (TpBaseConnection *conn, TpsipTextFactory *fac) { TpsipTextChannel *channel; - TpHandleRepoIface *contact_repo; TpHandle handle; const sip_t *sip = ev->sip; const char *text = ""; @@ -556,10 +556,7 @@ tpsip_nua_i_message_cb (TpBaseConnection *conn, } } - contact_repo = tp_base_connection_get_handles ( - conn, TP_HANDLE_TYPE_CONTACT); - - handle = tpsip_handle_parse_from (contact_repo, sip); + handle = tpsip_handle_by_requestor (conn, sip); if (!handle) { @@ -577,7 +574,7 @@ tpsip_nua_i_message_cb (TpBaseConnection *conn, TAG_END()); DEBUG("Got incoming message from <%s>", - tp_handle_inspect (contact_repo, handle)); + tpsip_handle_inspect (conn, handle)); channel = tpsip_text_factory_lookup_channel (fac, handle); @@ -588,7 +585,7 @@ tpsip_nua_i_message_cb (TpBaseConnection *conn, tpsip_text_channel_receive (channel, sip, handle, text, len); - tp_handle_unref (contact_repo, handle); + tpsip_handle_unref (conn, handle); end: g_free (allocated_text); @@ -597,7 +594,7 @@ end: } static void -connection_status_changed_cb (TpsipConnection *conn, +connection_status_changed_cb (TpBaseConnection *conn, guint status, guint reason, TpsipTextFactory *self) @@ -608,7 +605,7 @@ connection_status_changed_cb (TpsipConnection *conn, { case TP_CONNECTION_STATUS_CONNECTING: - priv->message_received_id = g_signal_connect (priv->conn, + priv->message_received_id = g_signal_connect (conn, "nua-event::nua_i_message", G_CALLBACK (tpsip_nua_i_message_cb), self); diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am index 04b14f2..e1d03b3 100644 --- a/tests/twisted/Makefile.am +++ b/tests/twisted/Makefile.am @@ -30,7 +30,8 @@ check-twisted: --sleep=$(CHECK_TWISTED_SLEEP) \ -- $(MAKE) check-TESTS \ TESTS="$(TWISTED_TESTS)" \ - TESTS_ENVIRONMENT="$(TESTS_ENVIRONMENT) $(PYTHON)" + TESTS_ENVIRONMENT="$(TESTS_ENVIRONMENT) $(PYTHON)" 2>&1 | \ + fgrep -v -e DeprecationWarning -e DigestAuthorizer EXTRA_DIST = \ $(TWISTED_TESTS) \ diff --git a/tests/twisted/test-self-alias.py b/tests/twisted/test-self-alias.py index 2eb4e7f..6c2e0a8 100644 --- a/tests/twisted/test-self-alias.py +++ b/tests/twisted/test-self-alias.py @@ -8,6 +8,8 @@ from servicetest import tp_name_prefix import dbus TEXT_TYPE = tp_name_prefix + '.Channel.Type.Text' +ALIASING_INTERFACE = tp_name_prefix + '.Connection.Interface.Aliasing' +CONTACTS_INTERFACE = tp_name_prefix + '.Connection.Interface.Contacts' def test(q, bus, conn, sip_proxy): conn.Connect() @@ -23,6 +25,14 @@ def test(q, bus, conn, sip_proxy): args=[[(self_handle, u'foo@bar.baz')]]) handle = conn.RequestHandles(1, ['sip:user@somewhere.com'])[0] + + assert ALIASING_INTERFACE in \ + conn.Properties.Get(CONTACTS_INTERFACE, "ContactAttributeInterfaces") + attrs = conn.Contacts.GetContactAttributes([self_handle, handle], + [ALIASING_INTERFACE], False) + assert ALIASING_INTERFACE + "/alias" in attrs[self_handle] + assert attrs[self_handle][ALIASING_INTERFACE + "/alias"] == u'foo@bar.baz' + conn.RequestChannel(TEXT_TYPE, 1, handle, True) event = q.expect('dbus-signal', signal='NewChannel') diff --git a/tpsip/Makefile.am b/tpsip/Makefile.am index 1186664..2a9df4d 100644 --- a/tpsip/Makefile.am +++ b/tpsip/Makefile.am @@ -13,12 +13,15 @@ AM_CPPFLAGS = @GLIB_CFLAGS@ @TELEPATHY_GLIB_CFLAGS@ @SOFIA_SIP_UA_CFLAGS@ \ AM_CFLAGS = $(ERROR_CFLAGS) $(COVERAGE_CFLAGS) -tpsip_includedir = $(includedir)/telepathy-sofiasip-0.6/tpsip +tpsip_includedir = $(includedir)/telepathy-sofiasip-0.7/tpsip tpsip_include_HEADERS = \ + base-connection.h \ + connection-aliasing.h sofia-decls.h \ codec-param-formats.h \ event-target.h \ + handles.h \ util.h BUILT_SOURCES = \ @@ -26,8 +29,12 @@ BUILT_SOURCES = \ signals-marshal.c libtpsip_la_SOURCES = \ + base-connection.c \ + base-connection-sofia.c \ + connection-aliasing.c \ codec-param-formats.c \ event-target.c \ + handles.c \ util.c nodist_libtpsip_la_SOURCES = \ diff --git a/src/sip-connection-sofia.c b/tpsip/base-connection-sofia.c index 29772fe..4c04eae 100644 --- a/src/sip-connection-sofia.c +++ b/tpsip/base-connection-sofia.c @@ -20,12 +20,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "sip-connection-sofia.h" +#include "config.h" +#include <tpsip/base-connection.h> #include <sofia-sip/su_tag_io.h> #define DEBUG_FLAG TPSIP_DEBUG_EVENTS -#include "debug.h" +#include "src/debug.h" static void priv_r_shutdown(int status, @@ -104,15 +105,15 @@ priv_r_get_params (int status, * See libsofia-sip-ua/nua/nua.h documentation. */ void -tpsip_connection_sofia_callback (nua_event_t event, - int status, - char const *phrase, - nua_t *nua, - TpsipConnection *conn, - nua_handle_t *nh, - TpsipEventTarget *target, - sip_t const *sip, - tagi_t tags[]) +tpsip_base_connection_sofia_callback (nua_event_t event, + int status, + char const *phrase, + nua_t *nua, + TpsipBaseConnection *conn, + nua_handle_t *nh, + TpsipEventTarget *target, + sip_t const *sip, + tagi_t tags[]) { DEBUG("event %s: %03d %s", nua_event_name (event), status, phrase); diff --git a/tpsip/base-connection.c b/tpsip/base-connection.c new file mode 100644 index 0000000..e437b00 --- /dev/null +++ b/tpsip/base-connection.c @@ -0,0 +1,205 @@ +/* + * sip-base-connection.c - source for SipBaseConnection + * Copyright (C) 2011 Nokia Corporation. + * Copyright (C) 2005-2007 Collabora Ltd. + * Copyright (C) 2005-2011 Nokia Corporation + * @author Kai Vehmanen <first.surname@nokia.com> + * @author Martti Mela <first.surname@nokia.com> + * @author Mikhail Zabaluev <mikhail.zabaluev@nokia.com> + * @author Pekka Pessi <pekka.pessi@nokia.com> + * + * Based on tpsip-connection and gabble implementation (gabble-connection). + * @author See gabble-connection.c + * + * 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 "config.h" + +#include <tpsip/base-connection.h> + +#include <telepathy-glib/telepathy-glib.h> +#include <tpsip/sofia-decls.h> + +struct _TpsipBaseConnectionPrivate +{ + su_root_t *sofia_root; + + unsigned dispose_has_run:1; unsigned :0; +}; + +enum { + PROP_NONE, + PROP_SOFIA_ROOT, + PROP_SOFIA_NUA, +}; + +/* ---------------------------------------------------------------------- */ +/* GObject implementation */ + +static void event_target_iface_init (gpointer iface, gpointer data) {} + +G_DEFINE_TYPE_WITH_CODE (TpsipBaseConnection, + tpsip_base_connection, TP_TYPE_BASE_CONNECTION, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACTS, + tp_contacts_mixin_iface_init); + G_IMPLEMENT_INTERFACE (TPSIP_TYPE_EVENT_TARGET, event_target_iface_init); +); + +static void +tpsip_base_connection_init (TpsipBaseConnection *self) +{ + GObject *object = G_OBJECT (self); + TpBaseConnection *base = TP_BASE_CONNECTION (self); + + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TPSIP_TYPE_BASE_CONNECTION, + TpsipBaseConnectionPrivate); + + tp_contacts_mixin_init (object, + G_STRUCT_OFFSET (TpsipBaseConnection, contacts_mixin)); + + /* org.freedesktop.Telepathy.Connection attributes */ + tp_base_connection_register_with_contacts_mixin (base); +} + +static void +tpsip_base_connection_constructed(GObject *object) +{ + if (G_OBJECT_CLASS(tpsip_base_connection_parent_class)->constructed) + G_OBJECT_CLASS(tpsip_base_connection_parent_class)->constructed(object); +} + +static void +tpsip_base_connection_dispose(GObject *object) +{ + TpsipBaseConnection *self = TPSIP_BASE_CONNECTION(object); + + if (self->priv->dispose_has_run) + return; + self->priv->dispose_has_run = 1; + + G_OBJECT_CLASS(tpsip_base_connection_parent_class)->dispose(object); +} + +void +tpsip_base_connection_finalize(GObject *object) +{ + G_OBJECT_CLASS(tpsip_base_connection_parent_class)->finalize(object); +} + +static void +tpsip_base_connection_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + TpsipBaseConnection *self = TPSIP_BASE_CONNECTION (object); + TpsipBaseConnectionPrivate *priv = self->priv; + + switch (property_id) + { + case PROP_SOFIA_ROOT: + priv->sofia_root = g_value_get_pointer (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +tpsip_base_connection_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + TpsipBaseConnection *self = TPSIP_BASE_CONNECTION (object); + TpsipBaseConnectionPrivate *priv = self->priv; + + switch (property_id) + { + case PROP_SOFIA_ROOT: + g_value_set_pointer (value, priv->sofia_root); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* -------------------------------------------------------------------------- */ + +static void +tpsip_base_connection_class_init (TpsipBaseConnectionClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + + g_type_class_add_private (klass, sizeof (TpsipBaseConnectionPrivate)); + + object_class->constructed = tpsip_base_connection_constructed; + object_class->dispose = tpsip_base_connection_dispose; + object_class->finalize = tpsip_base_connection_finalize; + object_class->get_property = tpsip_base_connection_get_property; + object_class->set_property = tpsip_base_connection_set_property; + + g_object_class_install_property (object_class, + PROP_SOFIA_ROOT, + g_param_spec_pointer ("sofia-root", + "Sofia-SIP root", + "The root object for Sofia-SIP", + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, + PROP_SOFIA_NUA, + g_param_spec_pointer ("sofia-nua", + "Sofia-SIP UA", + "The UA object for Sofia-SIP", + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + tp_contacts_mixin_class_init (object_class, + G_STRUCT_OFFSET(TpsipBaseConnectionClass, contacts_mixin_class)); +} + +nua_handle_t * +tpsip_base_connection_create_handle (TpsipBaseConnection *self, + TpHandle tphandle) +{ + TpsipBaseConnectionClass *cls = TPSIP_BASE_CONNECTION_GET_CLASS (self); + + return cls->create_handle (self, tphandle); +} + +void +tpsip_base_connection_add_auth_handler (TpsipBaseConnection *self, + TpsipEventTarget *target) +{ + TpsipBaseConnectionClass *cls = TPSIP_BASE_CONNECTION_GET_CLASS (self); + + if (cls->add_auth_handler) + cls->add_auth_handler (self, target); +} + +void +tpsip_base_connection_save_event (TpsipBaseConnection *self, + nua_saved_event_t ret_saved [1]) +{ + nua_t *nua; + + g_object_get (self, "sofia-nua", &nua, NULL); + + nua_save_event (nua, ret_saved); +} diff --git a/tpsip/base-connection.h b/tpsip/base-connection.h new file mode 100644 index 0000000..b444aa2 --- /dev/null +++ b/tpsip/base-connection.h @@ -0,0 +1,92 @@ +/* + * sip-base-connection.h - Header for SipBaseConnection + * Copyright (C) 2005 Collabora Ltd. + * Copyright (C) 2005-2009 Nokia Corporation + * + * 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_BASE_CONNECTION_H__ +#define __TPSIP_BASE_CONNECTION_H__ + +#include <glib-object.h> + +#include <telepathy-glib/base-connection.h> +#include <telepathy-glib/contacts-mixin.h> + +#include <tpsip/sofia-decls.h> +#include <tpsip/event-target.h> + +G_BEGIN_DECLS + +typedef struct _TpsipBaseConnection TpsipBaseConnection; +typedef struct _TpsipBaseConnectionClass TpsipBaseConnectionClass; +typedef struct _TpsipBaseConnectionPrivate TpsipBaseConnectionPrivate; + +struct _TpsipBaseConnectionClass { + TpBaseConnectionClass parent_class; + TpContactsMixinClass contacts_mixin_class; + + nua_handle_t *(*create_handle) (TpsipBaseConnection *, TpHandle contact); + void (*add_auth_handler) (TpsipBaseConnection *, TpsipEventTarget *); +}; + +struct _TpsipBaseConnection { + TpBaseConnection parent; + TpContactsMixin contacts_mixin; + TpsipBaseConnectionPrivate *priv; +}; + +GType tpsip_base_connection_get_type (void) G_GNUC_CONST; + +/* TYPE MACROS */ +#define TPSIP_TYPE_BASE_CONNECTION \ + (tpsip_base_connection_get_type()) +#define TPSIP_BASE_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + TPSIP_TYPE_BASE_CONNECTION, TpsipBaseConnection)) +#define TPSIP_BASE_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), \ + TPSIP_TYPE_BASE_CONNECTION, TpsipBaseConnectionClass)) +#define TPSIP_IS_BASE_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), TPSIP_TYPE_BASE_CONNECTION)) +#define TPSIP_IS_BASE_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), TPSIP_TYPE_BASE_CONNECTION)) +#define TPSIP_BASE_CONNECTION_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + TPSIP_TYPE_BASE_CONNECTION, TpsipBaseConnectionClass)) + +/*********************************************************************** + * Functions for accessing Sofia-SIP interface handles + ***********************************************************************/ + +nua_handle_t *tpsip_base_connection_create_handle (TpsipBaseConnection *, + TpHandle contact); +void tpsip_base_connection_add_auth_handler (TpsipBaseConnection *self, + TpsipEventTarget *target); +void tpsip_base_connection_save_event (TpsipBaseConnection *self, + nua_saved_event_t ret_saved [1]); + +/** Callback for events delivered by the SIP stack. */ +void tpsip_base_connection_sofia_callback (nua_event_t event, + int status, char const *phrase, + nua_t *nua, TpsipBaseConnection *conn, + nua_handle_t *nh, TpsipEventTarget *target, + sip_t const *sip, + tagi_t tags[]); + +G_END_DECLS + +#endif /* #ifndef __TPSIP_BASE_CONNECTION_H__*/ diff --git a/src/conn-aliasing.c b/tpsip/connection-aliasing.c index 4b4a8a4..d8af0ef 100644 --- a/src/conn-aliasing.c +++ b/tpsip/connection-aliasing.c @@ -1,7 +1,8 @@ /* - * conn-aliasing.c - Aliasing interface implementation for TpsipConnection - * Copyright (C) 2008, 2009 Nokia Corporation + * connection-aliasing.c - Implementation for TpsipConnectionAliasing interface + * Copyright (C) 2008-2011 Nokia Corporation * @author Mikhail Zabaluev <mikhail.zabaluev@nokia.com> + * @author Pekka Pessi <pekka.pessi@nokia.com> * * This work is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,19 +19,76 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "conn-aliasing.h" +#include "config.h" + +#include <tpsip/connection-aliasing.h> +#include <tpsip/base-connection.h> +#include <tpsip/handles.h> #include <telepathy-glib/errors.h> #include <telepathy-glib/gtypes.h> #include <telepathy-glib/interfaces.h> #include <telepathy-glib/svc-connection.h> +#include <telepathy-glib/contacts-mixin.h> -#include "sip-connection-helpers.h" +#include "tpsip/handles.h" #include <string.h> #define DEBUG_FLAG TPSIP_DEBUG_CONNECTION -#include "debug.h" +#include "src/debug.h" + +enum { + PROP_NONE, + PROP_ALIAS, +}; + +static void +tpsip_connection_aliasing_base_init (gpointer klass) +{ + static gboolean initialized = FALSE; + + if (!initialized) + { + initialized = TRUE; + + g_object_interface_install_property (klass, + g_param_spec_string ("alias", "Alias", + "User's display name", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + } +} + +GType +tpsip_connection_aliasing_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) + { + static const GTypeInfo info = { + sizeof (TpsipConnectionAliasingInterface), + tpsip_connection_aliasing_base_init, /* base_init */ + NULL, /* base_finalize */ + NULL, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL /* instance_init */ + }; + + type = g_type_register_static (G_TYPE_INTERFACE, + "TpsipConnectionAliasingInterface", &info, 0); + + g_type_interface_add_prerequisite (type, TPSIP_TYPE_BASE_CONNECTION); + g_type_interface_add_prerequisite (type, + TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING); + } + + return type; +} static void tpsip_connection_get_alias_flags (TpSvcConnectionInterfaceAliasing *iface, @@ -46,7 +104,7 @@ tpsip_connection_get_alias_flags (TpSvcConnectionInterfaceAliasing *iface, } static gchar * -conn_get_default_alias (TpsipConnection *self, +conn_get_default_alias (TpBaseConnection *base, TpHandleRepoIface *contact_handles, TpHandle handle) { @@ -55,7 +113,7 @@ conn_get_default_alias (TpsipConnection *self, /* TODO: create our custom handle repo to be able to get the URL off it. * Then we can reuse the contact_handles parameter */ - url = tpsip_conn_get_contact_url (self, handle); + url = tpsip_handle_inspect_uri (base, handle); switch (url->url_type) { @@ -79,21 +137,20 @@ conn_get_default_alias (TpsipConnection *self, } static gchar * -conn_get_alias (TpsipConnection *self, +conn_get_alias (TpBaseConnection *base, 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); + g_object_get (base, "alias", &alias, NULL); } if (alias == NULL) - alias = conn_get_default_alias (self, contact_handles, handle); + alias = conn_get_default_alias (base, contact_handles, handle); g_assert (alias != NULL); DEBUG("handle %u got alias %s", handle, alias); @@ -106,8 +163,7 @@ tpsip_connection_request_aliases (TpSvcConnectionInterfaceAliasing *iface, const GArray *contacts, DBusGMethodInvocation *context) { - TpsipConnection *self = TPSIP_CONNECTION (iface); - TpBaseConnection *base = (TpBaseConnection *) self; + TpBaseConnection *base = TP_BASE_CONNECTION (iface); TpHandleRepoIface *contact_handles; GArray *aliases; gchar **res; @@ -135,7 +191,7 @@ tpsip_connection_request_aliases (TpSvcConnectionInterfaceAliasing *iface, handle = g_array_index (contacts, TpHandle, i); - alias = conn_get_alias (self, contact_handles, handle); + alias = conn_get_alias (base, contact_handles, handle); g_array_append_val (aliases, alias); } @@ -153,8 +209,7 @@ tpsip_connection_get_aliases (TpSvcConnectionInterfaceAliasing *iface, const GArray *contacts, DBusGMethodInvocation *context) { - TpsipConnection *self = TPSIP_CONNECTION (iface); - TpBaseConnection *base = (TpBaseConnection *) self; + TpBaseConnection *base = TP_BASE_CONNECTION (iface); TpHandleRepoIface *contact_handles; GHashTable *result; GError *error = NULL; @@ -182,7 +237,7 @@ tpsip_connection_get_aliases (TpSvcConnectionInterfaceAliasing *iface, handle = g_array_index (contacts, TpHandle, i); - alias = conn_get_alias (self, contact_handles, handle); + alias = conn_get_alias (base, contact_handles, handle); g_hash_table_insert (result, GUINT_TO_POINTER (handle), alias); } @@ -194,9 +249,8 @@ tpsip_connection_get_aliases (TpSvcConnectionInterfaceAliasing *iface, } static void -emit_self_alias_change (TpsipConnection *self, const gchar *alias) +emit_self_alias_change (TpBaseConnection *base, const gchar *alias) { - TpBaseConnection *base = (TpBaseConnection *) self; GPtrArray *change_data; GValue change_pair = { 0, }; @@ -210,7 +264,7 @@ emit_self_alias_change (TpsipConnection *self, const gchar *alias) 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); + tp_svc_connection_interface_aliasing_emit_aliases_changed (base, change_data); g_ptr_array_free (change_data, TRUE); g_value_unset (&change_pair); @@ -246,8 +300,7 @@ tpsip_connection_set_aliases (TpSvcConnectionInterfaceAliasing *iface, GHashTable *aliases, DBusGMethodInvocation *context) { - TpsipConnection *self = TPSIP_CONNECTION (iface); - TpBaseConnection *base = (TpBaseConnection *) self; + TpBaseConnection *base = TP_BASE_CONNECTION (iface); TpHandleRepoIface *contact_handles; const gchar *alias; gchar *default_alias; @@ -271,21 +324,21 @@ tpsip_connection_set_aliases (TpSvcConnectionInterfaceAliasing *iface, contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); - default_alias = conn_get_default_alias (self, + default_alias = conn_get_default_alias (base, contact_handles, base->self_handle); if (strcmp (alias, default_alias) == 0) { DEBUG("using default alias for self"); - g_object_set (self, "alias", NULL, NULL); + g_object_set (base, "alias", NULL, NULL); } else { DEBUG("setting alias for self: %s", alias); - g_object_set (self, "alias", alias, NULL); + g_object_set (base, "alias", alias, NULL); } - emit_self_alias_change (self, alias); + emit_self_alias_change (base, alias); g_free (default_alias); g_free (to_free); @@ -297,8 +350,7 @@ 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; + TpBaseConnection *base = TP_BASE_CONNECTION (obj); TpHandleRepoIface *contact_handles; guint i; @@ -315,7 +367,7 @@ tpsip_conn_aliasing_fill_contact_attributes (GObject *obj, val = tp_g_value_slice_new (G_TYPE_STRING); g_value_take_string (val, - conn_get_alias (self, contact_handles, handle)); + conn_get_alias (base, contact_handles, handle)); tp_contacts_mixin_set_contact_attribute (attributes_hash, handle, TP_IFACE_CONNECTION_INTERFACE_ALIASING "/alias", val); @@ -323,15 +375,16 @@ tpsip_conn_aliasing_fill_contact_attributes (GObject *obj, } void -tpsip_conn_aliasing_init (TpsipConnection *conn) +tpsip_connection_aliasing_init (gpointer instance) { - tp_contacts_mixin_add_contact_attributes_iface (G_OBJECT (conn), + tp_contacts_mixin_add_contact_attributes_iface (G_OBJECT (instance), TP_IFACE_CONNECTION_INTERFACE_ALIASING, tpsip_conn_aliasing_fill_contact_attributes); } + void -tpsip_conn_aliasing_iface_init (gpointer g_iface, gpointer iface_data) +tpsip_connection_aliasing_svc_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcConnectionInterfaceAliasingClass *klass = (TpSvcConnectionInterfaceAliasingClass *) g_iface; diff --git a/tpsip/connection-aliasing.h b/tpsip/connection-aliasing.h new file mode 100644 index 0000000..1b674d4 --- /dev/null +++ b/tpsip/connection-aliasing.h @@ -0,0 +1,58 @@ +/* + * tpsip/connection-aliasing.h - Aliasing interface implementation for SIP + * Copyright (C) 2008, 2011 Nokia Corporation + * @author Mikhail Zabaluev <mikhail.zabaluev@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_CONNECTION_ALIASING_H__ +#define __TPSIP_CONNECTION_ALIASING_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS + +typedef struct _TpsipConnectionAliasing TpsipConnectionAliasing; + +typedef struct _TpsipConnectionAliasingInterface +TpsipConnectionAliasingInterface; + +/* TYPE MACROS */ +#define TPSIP_TYPE_CONNECTION_ALIASING \ + (tpsip_connection_aliasing_get_type ()) +#define TPSIP_CONNECTION_ALIASING(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + TPSIP_TYPE_CONNECTION_ALIASING, TpsipConnectionAliasing)) +#define TPSIP_IS_CONNECTION_ALIASING(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), TPSIP_TYPE_CONNECTION_ALIASING)) +#define TPSIP_CONNECTION_ALIASING_GET_INTERFACE(obj) \ + (G_TYPE_INSTANCE_GET_INTERFACE((obj), \ + TPSIP_TYPE_CONNECTION_ALIASING, TpsipConnectionAliasingInterface)) + +struct _TpsipConnectionAliasingInterface { + GTypeInterface base_iface; +}; + +GType tpsip_connection_aliasing_get_type (void) G_GNUC_CONST; + +void tpsip_connection_aliasing_init (gpointer instance); + +void tpsip_connection_aliasing_svc_iface_init (gpointer g_iface, + gpointer iface_data); + +G_END_DECLS + +#endif /*__TPSIP_CONN_ALIASING_H__*/ diff --git a/tpsip/handles.c b/tpsip/handles.c new file mode 100644 index 0000000..55eb7e2 --- /dev/null +++ b/tpsip/handles.c @@ -0,0 +1,345 @@ +/* + * tpsip/handles.c - Handler helpers + * Copyright (C) 2005 Collabora Ltd. + * Copyright (C) 2006-2011 Nokia Corporation + * + * 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 "config.h" + +#include <stdlib.h> + +#include <tpsip/handles.h> +#include <sofia-sip/sip_header.h> + +#define DEBUG_FLAG TPSIP_DEBUG_CONNECTION +#include "src/debug.h" + +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_handle_inspect_uri (TpBaseConnection *base, + TpHandle handle) +{ + TpHandleRepoIface *repo; + GQuark url_quark; + url_t *url; + GError *error; + + repo = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); + + if (!tp_handle_is_valid (repo, 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 (repo, handle, url_quark); + + if (url == NULL) + { + url = url_make (NULL, tp_handle_inspect (repo, handle)); + + tp_handle_set_qdata (repo, handle, url_quark, url, free); + } + + return url; +} + +TpHandle +tpsip_handle_ensure (TpBaseConnection *conn, + url_t const *uri, + char const *alias) +{ + TpHandleRepoIface *repo; + gchar *str; + TpHandle handle; + + g_return_val_if_fail (TP_IS_BASE_CONNECTION (conn), 0); + g_return_val_if_fail (uri != NULL, 0); + + repo = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT); + + str = url_as_string (NULL, uri); + + handle = tp_handle_ensure (repo, str, NULL, NULL); + + su_free (NULL, str); + + /* TODO: set qdata for the alias */ + + return handle; +} + +TpHandle +tpsip_handle_by_requestor (TpBaseConnection *conn, + sip_t const *sip) +{ + url_t const *uri; + char const *display; + + g_return_val_if_fail (sip != NULL, 0); + g_return_val_if_fail (sip->sip_from != NULL, 0); + + uri = sip->sip_from->a_url; + display = sip->sip_from->a_display; + + return tpsip_handle_ensure (conn, uri, display); +} + +void +tpsip_handle_unref (TpBaseConnection *conn, + TpHandle handle) +{ + TpHandleRepoIface *repo; + + g_return_if_fail (TP_IS_BASE_CONNECTION (conn)); + g_return_if_fail (handle != 0); + + repo = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT); + + tp_handle_unref (repo, handle); +} + +char const * +tpsip_handle_inspect (TpBaseConnection *conn, + TpHandle handle) +{ + TpHandleRepoIface *repo; + + g_return_val_if_fail (TP_IS_BASE_CONNECTION (conn), NULL); + g_return_val_if_fail (handle != 0, NULL); + + repo = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT); + + return tp_handle_inspect (repo, handle); +} + +static gboolean +priv_is_host (const gchar* str) +{ + static GRegex *host_regex = NULL; + +#define DOMAIN "[a-z0-9]([-a-z0-9]*[a-z0-9])?" +#define TLD "[a-z]([-a-z0-9]*[a-z0-9])?" + + if (host_regex == NULL) + { + GError *error = NULL; + + host_regex = g_regex_new ("^(" + "("DOMAIN"\\.)*"TLD"\\.?|" /* host name */ + "[0-9]{1,3}(\\.[0-9]{1,3}){3}|" /* IPv4 address */ + "\\[[0-9a-f:.]\\]" /* IPv6 address, sloppily */ + ")$", + G_REGEX_CASELESS | G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &error); + + if (error != NULL) + g_error ("failed to compile the host regex: %s", error->message); + } + +#undef DOMAIN +#undef TLD + + return g_regex_match (host_regex, str, 0, NULL); +} + +static gboolean +priv_is_tel_num (const gchar *str) +{ + static GRegex *tel_num_regex = NULL; + + if (tel_num_regex == NULL) + { + GError *error = NULL; + + tel_num_regex = g_regex_new ( + "^\\s*[\\+(]?\\s*[0-9][-.0-9()\\s]*$", + G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &error); + + if (error != NULL) + g_error ("failed to compile the telephone number regex: %s", + error->message); + } + + return g_regex_match (tel_num_regex, str, 0, NULL); +} + +/* Strip the non-essential characters from a string regarded as + * a telephone number */ +static gchar * +priv_strip_tel_num (const gchar *fuzzy) +{ + static GRegex *cruft_regex = NULL; + + if (cruft_regex == NULL) + { + GError *error = NULL; + + cruft_regex = g_regex_new ("[^+0-9]+", + G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &error); + + if (error != NULL) + g_error ("failed to compile the non-essential " + "telephone number cruft regex: %s", error->message); + } + + return g_regex_replace_literal (cruft_regex, fuzzy, -1, 0, "", 0, NULL); +} + +static const char * +priv_lowercase_url_part (su_home_t *home, const char *src) +{ + size_t n = 0; + size_t i; + char *res; + + for (i = 0; src[i]; i++) + { + if (g_ascii_isupper (src[i])) + { + n = i + strlen (src + i); + break; + } + } + + if (!src[i]) + return src; + + res = su_alloc (home, n + 1); + memcpy (res, src, i); + for (; i < n; i++) + res[i] = g_ascii_tolower (src[i]); + res[i] = '\0'; + + return (const char *) res; +} + +#define TPSIP_RESERVED_CHARS_ALLOWED_IN_USERNAME "!*'()&=+$,;?/" + +gchar * +tpsip_normalize_contact (const gchar *sipuri, + const url_t *base_url, + const gchar *transport, + GError **error) +{ + su_home_t home[1] = { SU_HOME_INIT(home) }; + url_t *url; + gchar *retval = NULL; + char *c; + + url = url_make (home, sipuri); + + if (url == NULL || + (url->url_scheme == NULL && url->url_user == NULL)) + { + /* we got username or phone number, local to our domain */ + gchar *user; + + if (base_url == NULL || base_url->url_host == NULL) + { + WARNING ("bare name given, but no account URL is set"); + goto error; + } + + if (priv_is_tel_num (sipuri)) + { + user = priv_strip_tel_num (sipuri); + } + else + { + user = g_uri_escape_string (sipuri, + TPSIP_RESERVED_CHARS_ALLOWED_IN_USERNAME, FALSE); + } + + if (base_url->url_type == url_sips) + url = url_format (home, "sips:%s@%s", + user, base_url->url_host); + else + url = url_format (home, "sip:%s@%s", + user, base_url->url_host); + + g_free (user); + + if (!url) goto error; + } + else if (url->url_scheme == NULL) + { + /* Set the scheme to SIP or SIPS accordingly to the connection's + * transport preference */ + if (transport != NULL + && g_ascii_strcasecmp (transport, "tls") == 0) + { + url->url_type = url_sips; + url->url_scheme = "sips"; + } + else + { + url->url_type = url_sip; + url->url_scheme = "sip"; + } + } + + if (url_sanitize (url) != 0) goto error; + + /* scheme should've been set by now */ + if (url->url_scheme == NULL || (url->url_scheme[0] == 0)) + goto error; + + /* convert the scheme to lowercase */ + /* Note: we can't do it in place because url->url_scheme may point to + * a static string */ + url->url_scheme = priv_lowercase_url_part (home, url->url_scheme); + + /* Check that if we have '@', the username isn't empty. + * Note that we rely on Sofia-SIP to canonize the user name */ + if (url->url_user) + { + if (url->url_user[0] == 0) goto error; + } + + /* host should be set and valid */ + if (url->url_host == NULL || !priv_is_host (url->url_host)) + goto error; + + /* convert host to lowercase */ + for (c = (char *) url->url_host; *c; c++) + { + *c = g_ascii_tolower (*c); + } + + retval = g_strdup (url_as_string (home, url)); + +error: + if (retval == NULL) + g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_HANDLE, + "invalid SIP URI"); + + su_home_deinit (home); + return retval; +} diff --git a/tpsip/handles.h b/tpsip/handles.h new file mode 100644 index 0000000..53dbf93 --- /dev/null +++ b/tpsip/handles.h @@ -0,0 +1,47 @@ +/* + * tpsip/handle.h - Telepathy SIP handle management + * Copyright (C) 2011 Nokia Corporation + * @author Pekka Pessi <pekka.pessi@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_HANDLE_H +#define TPSIP_HANDLE_H + +#include <telepathy-glib/base-connection.h> +#include <sofia-sip/sip.h> + +G_BEGIN_DECLS + +TpHandle tpsip_handle_ensure (TpBaseConnection *, url_t const *, char const *); +TpHandle tpsip_handle_by_requestor (TpBaseConnection *, sip_t const *sip); +void tpsip_handle_unref (TpBaseConnection *, TpHandle handle); +char const *tpsip_handle_inspect (TpBaseConnection *, TpHandle handle); +const url_t *tpsip_handle_inspect_uri (TpBaseConnection *, TpHandle handle); + +gchar * tpsip_handle_normalize (TpHandleRepoIface *repo, + const gchar *sipuri, + gpointer context, + GError **error); + +gchar *tpsip_normalize_contact (const gchar *sipuri, + const url_t *base_url, + const gchar *transport, + GError **error); + +G_END_DECLS + +#endif /* !TPSIP_HANDLE_H */ diff --git a/tpsip/sofia-decls.h b/tpsip/sofia-decls.h index a24ed15..d58b3fe 100644 --- a/tpsip/sofia-decls.h +++ b/tpsip/sofia-decls.h @@ -33,12 +33,17 @@ * pointing to an event target object attached to this handle. */ -#define NUA_MAGIC_T struct _TpsipConnection +#define NUA_MAGIC_T struct _TpsipBaseConnection #define NUA_HMAGIC_T struct _TpsipEventTarget #define SU_ROOT_MAGIC_T struct _TpsipConnectionManager -#define SU_TIMER_ARG_T struct _TpsipConnection +#define SU_TIMER_ARG_T struct _TpsipBaseConnection #define SU_WAKEUP_ARG_T void +#define TPSIP_DEFAULT_STUN_PORT 3478 + +/* Maximum defer timeout for deferrable Sofia timers */ +#define TPSIP_DEFER_TIMEOUT 30 + #include <sofia-sip/nua.h> #include <sofia-sip/su.h> |