summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2010-11-18 18:16:28 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2010-11-18 18:16:28 +0000
commitc847c6bfd4e3d963fd7da2c481fc3078606a4ffe (patch)
treed98bda6a538dd5f5d8dcd99a3c6220ce35504adf
parent5c7b956faeffeda6b4ef2666750398fdb9bb0fba (diff)
Port TpsipConnectionManager to use TpBaseProtocol
write-mgr-file.c was completely replaced by the one from Gabble, with trivial changes in main().
-rw-r--r--src/Makefile.am2
-rw-r--r--src/protocol.c515
-rw-r--r--src/protocol.h75
-rw-r--r--src/sip-connection-manager.c428
-rw-r--r--src/write-mgr-file.c374
5 files changed, 920 insertions, 474 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 6684513..ca15a87 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -92,6 +92,8 @@ libtpsip_convenience_la_SOURCES = \
debug.c \
media-factory.h \
media-factory.c \
+ protocol.h \
+ protocol.c \
text-factory.h \
text-factory.c \
sip-connection-helpers.h \
diff --git a/src/protocol.c b/src/protocol.c
new file mode 100644
index 0000000..1c8bb57
--- /dev/null
+++ b/src/protocol.c
@@ -0,0 +1,515 @@
+/*
+ * protocol.c - source for TpsipProtocol
+ * Copyright (C) 2007-2010 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "protocol.h"
+
+#include <string.h>
+
+#include <telepathy-glib/telepathy-glib.h>
+#include <dbus/dbus-protocol.h>
+#include <dbus/dbus-glib.h>
+
+#include <tpsip/sofia-decls.h>
+#include <sofia-sip/su_glib.h>
+
+#define DEBUG_FLAG TPSIP_DEBUG_CONNECTION
+#include "debug.h"
+#include "media-factory.h"
+#include "sip-connection.h"
+#include "sip-connection-helpers.h"
+#include "text-factory.h"
+
+#define PROTOCOL_NAME "sip"
+#define ICON_NAME "im-" PROTOCOL_NAME
+#define VCARD_FIELD_NAME "x-" PROTOCOL_NAME
+#define ENGLISH_NAME "SIP"
+
+G_DEFINE_TYPE (TpsipProtocol,
+ tpsip_protocol,
+ TP_TYPE_BASE_PROTOCOL)
+
+enum {
+ PROP_SOFIA_ROOT = 1,
+};
+
+struct _TpsipProtocolPrivate
+{
+ su_root_t *sofia_root;
+};
+
+/* Used in the otherwise-unused offset field of the TpCMParamSpec. The first
+ * one is nonzero to catch implicit zero-initialization. */
+enum {
+ PARAM_EASY = 1,
+ PARAM_SET_SEPARATELY
+};
+
+static TpCMParamSpec tpsip_params[] = {
+ /* Account (a sip: URI)
+ *
+ * FIXME: validate account SIP URI properly, using appropriate RFCs */
+ { "account", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
+ TP_CONN_MGR_PARAM_FLAG_REQUIRED | TP_CONN_MGR_PARAM_FLAG_REGISTER,
+ NULL, PARAM_SET_SEPARATELY, tp_cm_param_filter_string_nonempty, NULL },
+
+ /* Username to register with, if different than in the account URI */
+ { "auth-user", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
+ 0, NULL, PARAM_EASY },
+
+ /* Password */
+ { "password", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
+ TP_CONN_MGR_PARAM_FLAG_SECRET, NULL, PARAM_EASY },
+
+ /* Display name for self */
+ { "alias", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL, PARAM_EASY,
+ /* setting a 0-length alias makes no sense */
+ tp_cm_param_filter_string_nonempty, NULL },
+
+ /* Registrar */
+ { "registrar", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL,
+ PARAM_EASY },
+
+ /* Used to compose proxy URI */
+ { "proxy-host", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL,
+ PARAM_SET_SEPARATELY },
+ { "port", DBUS_TYPE_UINT16_AS_STRING, G_TYPE_UINT,
+ TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(SIP_DEFAULT_PORT),
+ PARAM_SET_SEPARATELY, tp_cm_param_filter_uint_nonzero },
+ { "transport", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
+ TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, "auto", PARAM_SET_SEPARATELY },
+
+ /* Enables loose routing as per RFC 3261 */
+ { "loose-routing", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN,
+ TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(FALSE),
+ PARAM_EASY },
+
+ /* Used to enable proactive NAT traversal techniques */
+ { "discover-binding", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN,
+ TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(TRUE),
+ PARAM_EASY },
+
+ /* Mechanism used for connection keepalive maintenance */
+ { "keepalive-mechanism", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
+ TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, "auto", PARAM_SET_SEPARATELY },
+
+ /* Keep-alive interval */
+ { "keepalive-interval", DBUS_TYPE_UINT32_AS_STRING, G_TYPE_UINT,
+ TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(0), PARAM_EASY },
+
+ /* Use SRV DNS lookup to discover STUN server */
+ { "discover-stun", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN,
+ TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(TRUE), PARAM_EASY },
+
+ /* STUN server */
+ { "stun-server", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL,
+ PARAM_EASY },
+
+ /* STUN port */
+ { "stun-port", DBUS_TYPE_UINT16_AS_STRING, G_TYPE_UINT,
+ TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT,
+ GUINT_TO_POINTER(TPSIP_DEFAULT_STUN_PORT), PARAM_EASY,
+ tp_cm_param_filter_uint_nonzero },
+
+ /* If the session content cannot be modified once initially set up */
+ { "immutable-streams", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN,
+ TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(FALSE),
+ PARAM_EASY },
+
+ /* Local IP address to use, workaround purposes only */
+ { "local-ip-address", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
+ 0, NULL, PARAM_EASY },
+
+ /* Local port for SIP, workaround purposes only */
+ { "local-port", DBUS_TYPE_UINT16_AS_STRING, G_TYPE_UINT, 0, NULL,
+ PARAM_EASY },
+
+ /* Extra-realm authentication */
+ { "extra-auth-user", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
+ 0, NULL, PARAM_EASY },
+ { "extra-auth-password", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
+ TP_CONN_MGR_PARAM_FLAG_SECRET, NULL, PARAM_EASY },
+
+ { NULL }
+};
+
+static void
+tpsip_protocol_init (TpsipProtocol *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TPSIP_TYPE_PROTOCOL,
+ TpsipProtocolPrivate);
+}
+
+static const TpCMParamSpec *
+get_parameters (TpBaseProtocol *self G_GNUC_UNUSED)
+{
+ return tpsip_params;
+}
+
+static TpsipConnectionKeepaliveMechanism
+priv_parse_keepalive (const gchar *str)
+{
+ if (str == NULL || strcmp (str, "auto") == 0)
+ return TPSIP_CONNECTION_KEEPALIVE_AUTO;
+ if (strcmp (str, "register") == 0)
+ return TPSIP_CONNECTION_KEEPALIVE_REGISTER;
+ if (strcmp (str, "options") == 0)
+ return TPSIP_CONNECTION_KEEPALIVE_OPTIONS;
+ if (strcmp (str, "stun") == 0)
+ return TPSIP_CONNECTION_KEEPALIVE_STUN;
+ if (strcmp (str, "off") == 0)
+ return TPSIP_CONNECTION_KEEPALIVE_NONE;
+
+ WARNING ("unsupported keepalive-method value \"%s\", falling back to auto", str);
+ return TPSIP_CONNECTION_KEEPALIVE_AUTO;
+}
+
+static gchar *
+priv_compose_proxy_uri (const gchar *host,
+ const gchar *transport,
+ guint port)
+{
+ const gchar *scheme = "sip";
+
+ if (host == NULL)
+ return NULL;
+
+ /* Set scheme to SIPS if transport is TLS */
+
+ if (transport != NULL && !g_ascii_strcasecmp (transport, "tls"))
+ scheme = "sips";
+
+ /* Format the resulting URI */
+
+ if (port)
+ return g_strdup_printf ("%s:%s:%u", scheme, host, port);
+ else
+ return g_strdup_printf ("%s:%s", scheme, host);
+}
+
+/**
+ * Returns a default SIP proxy address based on the public
+ * SIP address 'sip_address' and . For instance
+ * "sip:first.surname@company.com" would result in "sip:company.com".
+ * The SIP stack will further utilize DNS lookups to find the IP address
+ * for the SIP server responsible for the domain "company.com".
+ */
+static gchar *
+priv_compose_default_proxy_uri (const gchar *sip_address,
+ const gchar *transport)
+{
+ char *result = NULL;
+ char *host;
+ char *found;
+
+ g_return_val_if_fail (sip_address != NULL, NULL);
+
+ /* skip sip and sips prefixes, updating transport if necessary */
+ found = strchr (sip_address, ':');
+ if (found != NULL) {
+ if (g_ascii_strncasecmp ("sip:", sip_address, 4) == 0)
+ ;
+ else if (g_ascii_strncasecmp ("sips:", sip_address, 5) == 0)
+ {
+ if (transport == NULL ||
+ strcmp (transport, "auto") == 0)
+ transport = "tls";
+ }
+ else
+ {
+ /* error, unknown URI prefix */
+ return NULL;
+ }
+
+ sip_address = found + 1;
+ }
+
+ /* skip userinfo */
+ found = strchr (sip_address, '@');
+ if (found != NULL)
+ sip_address = found + 1;
+
+ /* copy rest of the string */
+ host = g_strdup (sip_address);
+
+ /* mark end (before uri-parameters defs or headers) */
+ found = strchr (host, ';');
+ if (found == NULL)
+ found = strchr (host, '?');
+ if (found != NULL)
+ *found = '\0';
+
+ result = priv_compose_proxy_uri (host, transport, 0);
+
+ g_free (host);
+
+ return result;
+}
+
+static TpBaseConnection *
+new_connection (TpBaseProtocol *protocol,
+ GHashTable *params,
+ GError **error)
+{
+ TpsipProtocol *self = TPSIP_PROTOCOL (protocol);
+ TpsipConnection *conn;
+ guint i;
+ const gchar *account;
+ const gchar *transport;
+ const gchar *proxy_host;
+ guint16 port;
+ gchar *proxy;
+ TpsipConnectionKeepaliveMechanism keepalive_mechanism;
+
+ account = tp_asv_get_string (params, "account");
+ transport = tp_asv_get_string (params, "transport");
+ port = tp_asv_get_uint32 (params, "port", NULL);
+
+ conn = g_object_new (TPSIP_TYPE_CONNECTION,
+ "protocol", PROTOCOL_NAME,
+ "sofia-root", self->priv->sofia_root,
+ "address", account,
+ NULL);
+
+ proxy_host = tp_asv_get_string (params, "proxy-host");
+
+ if (tp_str_empty (proxy_host))
+ {
+ proxy = priv_compose_default_proxy_uri (account, transport);
+ DEBUG("set outbound proxy address to <%s>, based on <%s>", proxy,
+ account);
+ }
+ else
+ {
+ proxy = priv_compose_proxy_uri (proxy_host, transport, port);
+ }
+
+ g_object_set (conn,
+ "proxy", proxy,
+ NULL);
+ g_free (proxy);
+
+ if (!tp_str_empty (transport) && tp_strdiff (transport, "auto"))
+ g_object_set (conn,
+ "transport", transport,
+ NULL);
+
+ for (i = 0; tpsip_params[i].name != NULL; i++)
+ {
+ if (tpsip_params[i].offset == PARAM_SET_SEPARATELY)
+ {
+ DEBUG ("Parameter %s is handled specially", tpsip_params[i].name);
+ break;
+ }
+
+ g_assert (tpsip_params[i].offset == PARAM_EASY);
+
+ switch (tpsip_params[i].gtype)
+ {
+ case G_TYPE_STRING:
+ {
+ const gchar *s = tp_asv_get_string (params,
+ tpsip_params[i].name);
+
+ if (!tp_str_empty (s))
+ g_object_set (conn,
+ tpsip_params[i].name, s,
+ NULL);
+ }
+ break;
+
+ case G_TYPE_UINT:
+ {
+ gboolean valid = FALSE;
+ guint u = tp_asv_get_uint32 (params,
+ tpsip_params[i].name, &valid);
+
+ if (valid)
+ g_object_set (conn,
+ tpsip_params[i].name, u,
+ NULL);
+ }
+ break;
+
+ case G_TYPE_BOOLEAN:
+ {
+ gboolean valid = FALSE;
+ gboolean b = tp_asv_get_boolean (params, tpsip_params[i].name,
+ &valid);
+
+ if (valid)
+ g_object_set (conn,
+ tpsip_params[i].name, b,
+ NULL);
+ }
+ break;
+
+ default:
+ /* no other parameters have been written yet */
+ g_assert_not_reached ();
+ }
+ }
+
+ keepalive_mechanism = priv_parse_keepalive (tp_asv_get_string (params,
+ "keepalive-mechanism"));
+ g_object_set (conn,
+ "keepalive-mechanism", keepalive_mechanism,
+ NULL);
+
+ return TP_BASE_CONNECTION (conn);
+}
+
+static gchar *
+normalize_contact (TpBaseProtocol *self G_GNUC_UNUSED,
+ const gchar *contact,
+ GError **error)
+{
+ return tpsip_normalize_contact (contact, NULL, NULL, error);
+}
+
+static gchar *
+identify_account (TpBaseProtocol *self G_GNUC_UNUSED,
+ GHashTable *asv,
+ GError **error)
+{
+ const gchar *account = tp_asv_get_string (asv, "account");
+
+ g_assert (account != NULL);
+ return g_strdup (account);
+}
+
+static GStrv
+get_interfaces (TpBaseProtocol *self)
+{
+ return g_new0 (gchar *, 1);
+}
+
+static void
+get_connection_details (TpBaseProtocol *self,
+ GStrv *connection_interfaces,
+ GType **channel_managers,
+ gchar **icon_name,
+ gchar **english_name,
+ gchar **vcard_field)
+{
+ if (connection_interfaces != NULL)
+ {
+ *connection_interfaces = g_strdupv (
+ (GStrv) tpsip_connection_get_implemented_interfaces ());
+ }
+
+ if (channel_managers != NULL)
+ {
+ GType types[] = {
+ TPSIP_TYPE_TEXT_FACTORY,
+ TPSIP_TYPE_MEDIA_FACTORY,
+ G_TYPE_INVALID };
+
+ *channel_managers = g_memdup (types, sizeof(types));
+ }
+
+ if (icon_name != NULL)
+ {
+ *icon_name = g_strdup (ICON_NAME);
+ }
+
+ if (vcard_field != NULL)
+ {
+ *vcard_field = g_strdup (VCARD_FIELD_NAME);
+ }
+
+ if (english_name != NULL)
+ {
+ *english_name = g_strdup (ENGLISH_NAME);
+ }
+}
+
+static void
+tpsip_protocol_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TpsipProtocol *self = TPSIP_PROTOCOL (object);
+
+ switch (property_id)
+ {
+ case PROP_SOFIA_ROOT:
+ g_value_set_pointer (value, self->priv->sofia_root);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+tpsip_protocol_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ TpsipProtocol *self = TPSIP_PROTOCOL (object);
+
+ switch (property_id)
+ {
+ case PROP_SOFIA_ROOT:
+ self->priv->sofia_root = g_value_get_pointer (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+tpsip_protocol_class_init (TpsipProtocolClass *klass)
+{
+ TpBaseProtocolClass *base_class = (TpBaseProtocolClass *) klass;
+ GObjectClass *object_class = (GObjectClass *) klass;
+ GParamSpec *param_spec;
+
+ g_type_class_add_private (klass, sizeof (TpsipProtocolPrivate));
+
+ base_class->get_parameters = get_parameters;
+ base_class->new_connection = new_connection;
+ base_class->normalize_contact = normalize_contact;
+ base_class->identify_account = identify_account;
+ base_class->get_interfaces = get_interfaces;
+ base_class->get_connection_details = get_connection_details;
+
+ object_class->get_property = tpsip_protocol_get_property;
+ object_class->set_property = tpsip_protocol_set_property;
+
+ param_spec = 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_ROOT,
+ param_spec);
+}
+
+TpBaseProtocol *
+tpsip_protocol_new (su_root_t *sofia_root)
+{
+ return g_object_new (TPSIP_TYPE_PROTOCOL,
+ "name", PROTOCOL_NAME,
+ "sofia-root", sofia_root,
+ NULL);
+}
diff --git a/src/protocol.h b/src/protocol.h
new file mode 100644
index 0000000..7470af1
--- /dev/null
+++ b/src/protocol.h
@@ -0,0 +1,75 @@
+/*
+ * protocol.h - header for TpsipProtocol
+ * Copyright (C) 2007-2010 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef TPSIP_PROTOCOL_H
+#define TPSIP_PROTOCOL_H
+
+#include <glib-object.h>
+#include <telepathy-glib/base-protocol.h>
+
+#include <tpsip/sofia-decls.h>
+#include <sofia-sip/su_glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _TpsipProtocol TpsipProtocol;
+typedef struct _TpsipProtocolPrivate TpsipProtocolPrivate;
+typedef struct _TpsipProtocolClass TpsipProtocolClass;
+typedef struct _TpsipProtocolClassPrivate TpsipProtocolClassPrivate;
+
+struct _TpsipProtocolClass {
+ TpBaseProtocolClass parent_class;
+
+ TpsipProtocolClassPrivate *priv;
+};
+
+struct _TpsipProtocol {
+ TpBaseProtocol parent;
+
+ TpsipProtocolPrivate *priv;
+};
+
+GType tpsip_protocol_get_type (void);
+
+#define TPSIP_TYPE_PROTOCOL \
+ (tpsip_protocol_get_type ())
+#define TPSIP_PROTOCOL(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ TPSIP_TYPE_PROTOCOL, \
+ TpsipProtocol))
+#define TPSIP_PROTOCOL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ TPSIP_TYPE_PROTOCOL, \
+ TpsipProtocolClass))
+#define TPSIP_IS_PROTOCOL_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ TPSIP_TYPE_PROTOCOL))
+#define TPSIP_PROTOCOL_GET_CLASS(klass) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ TPSIP_TYPE_PROTOCOL, \
+ TpsipProtocolClass))
+
+gchar *tpsip_protocol_normalize_contact (const gchar *id,
+ GError **error);
+
+TpBaseProtocol *tpsip_protocol_new (su_root_t *sofia_root);
+
+G_END_DECLS
+
+#endif
diff --git a/src/sip-connection-manager.c b/src/sip-connection-manager.c
index 7a33481..ecb882e 100644
--- a/src/sip-connection-manager.c
+++ b/src/sip-connection-manager.c
@@ -38,6 +38,7 @@
#include <tpsip/sofia-decls.h>
#include <sofia-sip/su_glib.h>
+#include "protocol.h"
#include "sip-connection-manager.h"
#include "sip-connection.h"
@@ -48,165 +49,6 @@
G_DEFINE_TYPE(TpsipConnectionManager, tpsip_connection_manager,
TP_TYPE_BASE_CONNECTION_MANAGER)
-/* private structure *//* typedef struct _TpsipConnectionManagerPrivate TpsipConnectionManagerPrivate; */
-
-typedef struct {
- gchar *account;
- gchar *auth_user;
- gchar *password;
- gchar *alias;
- gchar *registrar;
- gchar *proxy_host;
- guint port;
- gchar *transport;
- gboolean loose_routing;
- gboolean discover_binding;
- gchar *keepalive_mechanism;
- guint keepalive_interval;
- gboolean discover_stun;
- gchar *stun_server;
- guint stun_port;
- gboolean immutable_streams;
- gchar *local_ip_address;
- guint local_port;
- gchar *extra_auth_user;
- gchar *extra_auth_password;
-} TpsipConnParams;
-
-static void *
-alloc_params (void)
-{
- return g_slice_new0 (TpsipConnParams);
-}
-
-static void
-free_params (void *p)
-{
- TpsipConnParams *params = (TpsipConnParams *)p;
-
- g_free (params->account);
- g_free (params->auth_user);
- g_free (params->password);
- g_free (params->alias);
- g_free (params->registrar);
- g_free (params->proxy_host);
- g_free (params->transport);
- g_free (params->keepalive_mechanism);
- g_free (params->stun_server);
- g_free (params->local_ip_address);
- g_free (params->extra_auth_user);
- g_free (params->extra_auth_password);
-
- g_slice_free (TpsipConnParams, params);
-}
-
-enum {
- TPSIP_CONN_PARAM_ACCOUNT = 0,
- TPSIP_CONN_PARAM_AUTH_USER,
- TPSIP_CONN_PARAM_PASSWORD,
- TPSIP_CONN_PARAM_ALIAS,
- TPSIP_CONN_PARAM_REGISTRAR,
- TPSIP_CONN_PARAM_PROXY_HOST,
- TPSIP_CONN_PARAM_PORT,
- TPSIP_CONN_PARAM_TRANSPORT,
- TPSIP_CONN_PARAM_LOOSE_ROUTING,
- TPSIP_CONN_PARAM_DISCOVER_BINDING,
- TPSIP_CONN_PARAM_KEEPALIVE_MECHANISM,
- TPSIP_CONN_PARAM_KEEPALIVE_INTERVAL,
- TPSIP_CONN_PARAM_DISCOVER_STUN,
- TPSIP_CONN_PARAM_STUN_SERVER,
- TPSIP_CONN_PARAM_STUN_PORT,
- TPSIP_CONN_PARAM_IMMUTABLE_STREAMS,
- TPSIP_CONN_PARAM_LOCAL_IP_ADDRESS,
- TPSIP_CONN_PARAM_LOCAL_PORT,
- TPSIP_CONN_PARAM_EXTRA_AUTH_USER,
- TPSIP_CONN_PARAM_EXTRA_AUTH_PASSWORD,
- N_TPSIP_CONN_PARAMS
-};
-
-static const TpCMParamSpec tpsip_params[] = {
- /* Account (a sip: URI) */
- { "account", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- TP_CONN_MGR_PARAM_FLAG_REQUIRED | TP_CONN_MGR_PARAM_FLAG_REGISTER,
- NULL, G_STRUCT_OFFSET (TpsipConnParams, account) },
- /* Username to register with, if different than in the account URI */
- { "auth-user", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- 0, NULL, G_STRUCT_OFFSET (TpsipConnParams, auth_user) },
- /* Password */
- { "password", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- TP_CONN_MGR_PARAM_FLAG_SECRET,
- NULL, G_STRUCT_OFFSET (TpsipConnParams, password) },
- /* Display name for self */
- { "alias", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL,
- G_STRUCT_OFFSET(TpsipConnParams, alias),
- /* setting a 0-length alias makes no sense */
- tp_cm_param_filter_string_nonempty, NULL },
- /* Registrar */
- { "registrar", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- 0, NULL, G_STRUCT_OFFSET (TpsipConnParams, registrar) },
- /* Used to compose proxy URI */
- { "proxy-host", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- 0, NULL, G_STRUCT_OFFSET (TpsipConnParams, proxy_host) },
- /* Used to compose proxy URI */
- { "port", DBUS_TYPE_UINT16_AS_STRING, G_TYPE_UINT,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(SIP_DEFAULT_PORT),
- G_STRUCT_OFFSET (TpsipConnParams, port) },
- /* Used to compose proxy URI */
- { "transport", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, "auto",
- G_STRUCT_OFFSET (TpsipConnParams, transport) },
- /* Enables loose routing as per RFC 3261 */
- { "loose-routing", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(FALSE),
- G_STRUCT_OFFSET (TpsipConnParams, loose_routing) },
- /* Used to enable proactive NAT traversal techniques */
- { "discover-binding", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(TRUE),
- G_STRUCT_OFFSET (TpsipConnParams, discover_binding) },
- /* Mechanism used for connection keepalive maintenance */
- { "keepalive-mechanism", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, "auto",
- G_STRUCT_OFFSET (TpsipConnParams, keepalive_mechanism) },
- /* Keep-alive interval */
- { "keepalive-interval", DBUS_TYPE_UINT32_AS_STRING, G_TYPE_UINT,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(0),
- G_STRUCT_OFFSET (TpsipConnParams, keepalive_interval) },
- /* Use SRV DNS lookup to discover STUN server */
- { "discover-stun", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(TRUE),
- G_STRUCT_OFFSET (TpsipConnParams, discover_stun) },
- /* STUN server */
- { "stun-server", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- 0, NULL, G_STRUCT_OFFSET (TpsipConnParams, stun_server) },
- /* STUN port */
- { "stun-port", DBUS_TYPE_UINT16_AS_STRING, G_TYPE_UINT,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT,
- GUINT_TO_POINTER(TPSIP_DEFAULT_STUN_PORT),
- G_STRUCT_OFFSET (TpsipConnParams, stun_port) },
- /* If the session content cannot be modified once initially set up */
- { "immutable-streams", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN,
- TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(FALSE),
- G_STRUCT_OFFSET (TpsipConnParams, immutable_streams) },
- /* Local IP address to use, workaround purposes only */
- { "local-ip-address", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- 0, NULL, G_STRUCT_OFFSET (TpsipConnParams, local_ip_address) },
- /* Local port for SIP, workaround purposes only */
- { "local-port", DBUS_TYPE_UINT16_AS_STRING, G_TYPE_UINT,
- 0, NULL, G_STRUCT_OFFSET (TpsipConnParams, local_port) },
- /* Extra-realm authentication */
- { "extra-auth-user", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- 0, NULL, G_STRUCT_OFFSET (TpsipConnParams, extra_auth_user) },
- { "extra-auth-password", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
- TP_CONN_MGR_PARAM_FLAG_SECRET,
- NULL, G_STRUCT_OFFSET (TpsipConnParams, extra_auth_password) },
- { NULL, NULL, 0, 0, NULL, 0 }
-};
-
-const TpCMProtocolSpec tpsip_protocols[] = {
- { "sip", tpsip_params, alloc_params, free_params },
- { NULL, NULL }
-};
-
struct _TpsipConnectionManagerPrivate
{
su_root_t *sofia_root;
@@ -237,10 +79,24 @@ tpsip_connection_manager_init (TpsipConnectionManager *obj)
#endif
}
+static void
+tpsip_connection_manager_constructed (GObject *object)
+{
+ TpsipConnectionManager *self = TPSIP_CONNECTION_MANAGER (object);
+ TpBaseConnectionManager *base = (TpBaseConnectionManager *) self;
+ void (*constructed) (GObject *) =
+ ((GObjectClass *) tpsip_connection_manager_parent_class)->constructed;
+ TpBaseProtocol *protocol;
+
+ if (constructed != NULL)
+ constructed (object);
+
+ protocol = tpsip_protocol_new (self->priv->sofia_root);
+ tp_base_connection_manager_add_protocol (base, protocol);
+ g_object_unref (protocol);
+}
+
static void tpsip_connection_manager_finalize (GObject *object);
-static TpBaseConnection *tpsip_connection_manager_new_connection (
- TpBaseConnectionManager *base, const gchar *proto,
- TpIntSet *params_present, void *parsed_params, GError **error);
static void
tpsip_connection_manager_class_init (TpsipConnectionManagerClass *klass)
@@ -251,11 +107,10 @@ tpsip_connection_manager_class_init (TpsipConnectionManagerClass *klass)
g_type_class_add_private (klass, sizeof (TpsipConnectionManagerPrivate));
+ object_class->constructed = tpsip_connection_manager_constructed;
object_class->finalize = tpsip_connection_manager_finalize;
- base_class->new_connection = tpsip_connection_manager_new_connection;
base_class->cm_dbus_name = "sofiasip";
- base_class->protocol_params = tpsip_protocols;
}
void
@@ -279,248 +134,3 @@ tpsip_connection_manager_finalize (GObject *object)
G_OBJECT_CLASS (tpsip_connection_manager_parent_class)->finalize (object);
}
-
-static gchar *
-priv_compose_proxy_uri (const gchar *host,
- const gchar *transport,
- guint port)
-{
- const gchar *scheme = "sip";
-
- if (host == NULL)
- return NULL;
-
- /* Set scheme to SIPS if transport is TLS */
-
- if (transport != NULL && !g_ascii_strcasecmp (transport, "tls"))
- scheme = "sips";
-
- /* Format the resulting URI */
-
- if (port)
- return g_strdup_printf ("%s:%s:%u", scheme, host, port);
- else
- return g_strdup_printf ("%s:%s", scheme, host);
-}
-
-/**
- * Returns a default SIP proxy address based on the public
- * SIP address 'sip_address' and . For instance
- * "sip:first.surname@company.com" would result in "sip:company.com".
- * The SIP stack will further utilize DNS lookups to find the IP address
- * for the SIP server responsible for the domain "company.com".
- */
-static gchar *
-priv_compose_default_proxy_uri (const gchar *sip_address,
- const gchar *transport)
-{
- char *result = NULL;
- char *host;
- char *found;
-
- g_return_val_if_fail (sip_address != NULL, NULL);
-
- /* skip sip and sips prefixes, updating transport if necessary */
- found = strchr (sip_address, ':');
- if (found != NULL) {
- if (g_ascii_strncasecmp ("sip:", sip_address, 4) == 0)
- ;
- else if (g_ascii_strncasecmp ("sips:", sip_address, 5) == 0)
- {
- if (transport == NULL ||
- strcmp (transport, "auto") == 0)
- transport = "tls";
- }
- else
- {
- /* error, unknown URI prefix */
- return NULL;
- }
-
- sip_address = found + 1;
- }
-
- /* skip userinfo */
- found = strchr (sip_address, '@');
- if (found != NULL)
- sip_address = found + 1;
-
- /* copy rest of the string */
- host = g_strdup (sip_address);
-
- /* mark end (before uri-parameters defs or headers) */
- found = strchr (host, ';');
- if (found == NULL)
- found = strchr (host, '?');
- if (found != NULL)
- *found = '\0';
-
- result = priv_compose_proxy_uri (host, transport, 0);
-
- g_free (host);
-
- return result;
-}
-
-static TpsipConnectionKeepaliveMechanism
-priv_parse_keepalive (const gchar *str)
-{
- if (str == NULL || strcmp (str, "auto") == 0)
- return TPSIP_CONNECTION_KEEPALIVE_AUTO;
- if (strcmp (str, "register") == 0)
- return TPSIP_CONNECTION_KEEPALIVE_REGISTER;
- if (strcmp (str, "options") == 0)
- return TPSIP_CONNECTION_KEEPALIVE_OPTIONS;
- if (strcmp (str, "stun") == 0)
- return TPSIP_CONNECTION_KEEPALIVE_STUN;
- if (strcmp (str, "off") == 0)
- return TPSIP_CONNECTION_KEEPALIVE_NONE;
-
- WARNING ("unsupported keepalive-method value \"%s\", falling back to auto", str);
- return TPSIP_CONNECTION_KEEPALIVE_AUTO;
-}
-
-#define SET_PROPERTY_IF_PARAM_SET(prop, param, member) \
- if (tp_intset_is_member (params_present, param)) \
- { \
- g_object_set (connection, prop, member, NULL); \
- }
-
-#define NULLIFY_IF_EMPTY(param) \
- if ((param) != NULL && (param)[0] == '\0') \
- param = NULL;
-
-static gboolean
-check_not_empty_if_present (const gchar *name,
- const gchar *value,
- GError **error)
-{
- if (value != NULL && value[0] == '\0')
- {
- g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
- "If supplied, '%s' account parameter may not be empty", name);
- return FALSE;
- }
- return TRUE;
-}
-
-static TpBaseConnection *
-tpsip_connection_manager_new_connection (TpBaseConnectionManager *base,
- const gchar *proto,
- TpIntSet *params_present,
- void *parsed_params,
- GError **error)
-{
- TpsipConnectionManager *self = TPSIP_CONNECTION_MANAGER (base);
- TpsipConnectionManagerPrivate *priv = TPSIP_CONNECTION_MANAGER_GET_PRIVATE (self);
- TpBaseConnection *connection = NULL;
- TpsipConnParams *params = (TpsipConnParams *)parsed_params;
- gchar *proxy = NULL;
- TpsipConnectionKeepaliveMechanism keepalive_mechanism;
-
- if (strcmp (proto, "sip")) {
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED,
- "This connection manager only implements protocol 'sip', not '%s'",
- proto);
- return NULL;
- }
-
- /* TpBaseConnectionManager code has already checked that required params
- * are present (but not that they are non-empty, if we're using >= 0.5.8)
- */
- g_assert (params->account);
-
- /* FIXME: validate account SIP URI properly, using appropriate RFCs */
- if (!check_not_empty_if_present ("account", params->account, error))
- return FALSE;
- NULLIFY_IF_EMPTY (params->auth_user);
- NULLIFY_IF_EMPTY (params->password);
- /* FIXME: validate registrar SIP URI properly, using appropriate RFCs */
- NULLIFY_IF_EMPTY (params->registrar);
- /* FIXME: validate proxy host properly */
- NULLIFY_IF_EMPTY (params->proxy_host);
- /* FIXME: check against the list (which presumably exists) of valid
- * transports */
- NULLIFY_IF_EMPTY (params->transport);
- /* FIXME: check against the list (which presumably exists) of valid
- * KA mechanisms */
- NULLIFY_IF_EMPTY (params->keepalive_mechanism);
- /* FIXME: validate STUN server properly */
- NULLIFY_IF_EMPTY (params->stun_server);
- /* FIXME: validate local IP address properly */
- NULLIFY_IF_EMPTY (params->local_ip_address);
- NULLIFY_IF_EMPTY (params->extra_auth_user);
- NULLIFY_IF_EMPTY (params->extra_auth_password);
-
- DEBUG("New SIP connection to %s", params->account);
-
- connection = (TpBaseConnection *)g_object_new(TPSIP_TYPE_CONNECTION,
- "protocol", "sip",
- "sofia-root", priv->sofia_root,
- "address", params->account,
- NULL);
-
- if (params->proxy_host == NULL) {
- proxy = priv_compose_default_proxy_uri (params->account,
- params->transport);
- DEBUG("set outbound proxy address to <%s>, based on <%s>", proxy, params->account);
- } else
- proxy = priv_compose_proxy_uri (params->proxy_host,
- params->transport,
- params->port);
-
- g_object_set (connection, "proxy", proxy, NULL);
- g_free (proxy);
-
- if (params->transport != NULL && strcmp (params->transport, "auto") != 0)
- g_object_set (connection, "transport", params->transport, NULL);
-
- SET_PROPERTY_IF_PARAM_SET ("auth-user", TPSIP_CONN_PARAM_AUTH_USER,
- params->auth_user);
-
- SET_PROPERTY_IF_PARAM_SET ("password", TPSIP_CONN_PARAM_PASSWORD,
- params->password);
-
- SET_PROPERTY_IF_PARAM_SET ("alias", TPSIP_CONN_PARAM_ALIAS,
- params->alias);
-
- SET_PROPERTY_IF_PARAM_SET ("registrar", TPSIP_CONN_PARAM_REGISTRAR,
- params->registrar);
-
- SET_PROPERTY_IF_PARAM_SET ("loose-routing", TPSIP_CONN_PARAM_LOOSE_ROUTING,
- params->loose_routing);
-
- SET_PROPERTY_IF_PARAM_SET ("discover-binding", TPSIP_CONN_PARAM_DISCOVER_BINDING,
- params->discover_binding);
-
- SET_PROPERTY_IF_PARAM_SET ("discover-stun", TPSIP_CONN_PARAM_DISCOVER_STUN,
- params->discover_stun);
-
- SET_PROPERTY_IF_PARAM_SET ("stun-server", TPSIP_CONN_PARAM_STUN_SERVER,
- params->stun_server);
-
- SET_PROPERTY_IF_PARAM_SET ("stun-port", TPSIP_CONN_PARAM_STUN_PORT,
- params->stun_port);
-
- SET_PROPERTY_IF_PARAM_SET ("immutable-streams", TPSIP_CONN_PARAM_IMMUTABLE_STREAMS,
- params->immutable_streams);
-
- SET_PROPERTY_IF_PARAM_SET ("keepalive-interval",
- TPSIP_CONN_PARAM_KEEPALIVE_INTERVAL, params->keepalive_interval);
-
- keepalive_mechanism = priv_parse_keepalive (params->keepalive_mechanism);
- g_object_set (connection, "keepalive-mechanism", keepalive_mechanism, NULL);
-
- SET_PROPERTY_IF_PARAM_SET ("local-ip-address", TPSIP_CONN_PARAM_LOCAL_IP_ADDRESS,
- params->local_ip_address);
-
- SET_PROPERTY_IF_PARAM_SET ("local-port", TPSIP_CONN_PARAM_LOCAL_PORT,
- params->local_port);
-
- SET_PROPERTY_IF_PARAM_SET ("extra-auth-user", TPSIP_CONN_PARAM_EXTRA_AUTH_USER,
- params->extra_auth_user);
- SET_PROPERTY_IF_PARAM_SET ("extra-auth-password", TPSIP_CONN_PARAM_EXTRA_AUTH_PASSWORD,
- params->extra_auth_password);
-
- return connection;
-}
diff --git a/src/write-mgr-file.c b/src/write-mgr-file.c
index e718d91..bf51a19 100644
--- a/src/write-mgr-file.c
+++ b/src/write-mgr-file.c
@@ -1,113 +1,357 @@
/*
- * write_mgr_file.c - utility to produce .manager files.
- * Copyright (C) 2006-2007 Collabora Ltd.
- * Copyright (C) 2006-2007 Nokia Corporation
+ * write_mgr_file.c - utility to produce gabble.manager. Part of Gabble.
+ * Copyright (C) 2006-2010 Collabora Ltd.
+ * Copyright (C) 2006-2010 Nokia Corporation
*
- * This work is free software; you can redistribute it and/or
+ * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * This work is distributed in the hope that it will be useful,
+ * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this work; if not, write to the Free Software
+ * License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "config.h"
+
#include <stdio.h>
+#include <string.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-protocol.h>
+#include <telepathy-glib/telepathy-glib.h>
-#include <telepathy-glib/enums.h>
-#include "sip-connection-manager.h"
+#include "protocol.h"
-/* Cloned straight from Gabble - this might eventually go in a library */
-static gchar *
-mgr_file_contents (const char *busname,
- const char *objpath,
- const TpCMProtocolSpec protocols[],
- GError **error)
+
+#define WRITE_STR(prop, key) \
+ { \
+ const gchar *val = tp_asv_get_string (props, prop); \
+ g_assert (!tp_str_empty (val)); \
+ g_key_file_set_string (f, section_name, key, val); \
+ }
+
+static void
+write_parameters (GKeyFile *f, gchar *section_name, TpBaseProtocol *protocol)
{
- GKeyFile *f = g_key_file_new();
- const TpCMProtocolSpec *protocol;
+ const TpCMParamSpec *parameters =
+ tp_base_protocol_get_parameters (protocol);
const TpCMParamSpec *row;
- g_key_file_set_string(f, "ConnectionManager", "BusName", busname);
- g_key_file_set_string(f, "ConnectionManager", "ObjectPath", objpath);
+ for (row = parameters; row->name; row++)
+ {
+ gchar *param_name = g_strdup_printf ("param-%s", row->name);
+ gchar *param_value = g_strdup_printf ("%s%s%s%s", row->dtype,
+ (row->flags & TP_CONN_MGR_PARAM_FLAG_REQUIRED ? " required" : ""),
+ (row->flags & TP_CONN_MGR_PARAM_FLAG_REGISTER ? " register" : ""),
+ (row->flags & TP_CONN_MGR_PARAM_FLAG_SECRET ? " secret" : ""));
+ g_key_file_set_string (f, section_name, param_name, param_value);
+ g_free (param_value);
+ g_free (param_name);
+ }
- for (protocol = protocols; protocol->name; protocol++)
+ for (row = parameters; row->name; row++)
{
- gchar *section_name = g_strdup_printf("Protocol %s", protocol->name);
+ if (row->flags & TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT)
+ {
+ gchar *default_name = g_strdup_printf ("default-%s", row->name);
- for (row = protocol->parameters; row->name; row++)
+ switch (row->gtype)
+ {
+ case G_TYPE_STRING:
+ g_key_file_set_string (f, section_name, default_name,
+ row->def);
+ break;
+ case G_TYPE_INT:
+ case G_TYPE_UINT:
+ g_key_file_set_integer (f, section_name, default_name,
+ GPOINTER_TO_INT(row->def));
+ break;
+ case G_TYPE_BOOLEAN:
+ g_key_file_set_boolean (f, section_name, default_name,
+ GPOINTER_TO_INT(row->def) ? 1 : 0);
+ break;
+ default:
+ /* can't be in the case because G_TYPE_STRV is actually a
+ * function */
+ if (row->gtype == G_TYPE_STRV)
+ {
+ g_key_file_set_string_list (f, section_name, default_name,
+ (const gchar **) row->def,
+ g_strv_length ((gchar **) row->def));
+ }
+ }
+ g_free (default_name);
+ }
+ }
+}
+
+static void
+write_rcc_property (GKeyFile *keyfile,
+ const gchar *group_name,
+ const gchar *key,
+ GValue *val)
+{
+ switch (G_VALUE_TYPE (val))
+ {
+ case G_TYPE_BOOLEAN:
{
- gchar *param_name = g_strdup_printf("param-%s", row->name);
- gchar *param_value = g_strdup_printf("%s%s%s%s", row->dtype,
- (row->flags & TP_CONN_MGR_PARAM_FLAG_REQUIRED ? " required" : ""),
- (row->flags & TP_CONN_MGR_PARAM_FLAG_REGISTER ? " register" : ""),
- (row->flags & TP_CONN_MGR_PARAM_FLAG_SECRET ? " secret" : ""));
- g_key_file_set_string(f, section_name, param_name, param_value);
- g_free(param_value);
- g_free(param_name);
+ gchar *kf_key = g_strconcat (key,
+ " " DBUS_TYPE_BOOLEAN_AS_STRING, NULL);
+ g_key_file_set_boolean (keyfile, group_name, kf_key,
+ g_value_get_boolean (val));
+ g_free (kf_key);
+ break;
}
- for (row = protocol->parameters; row->name; row++)
+ case G_TYPE_STRING:
{
- if (row->flags & TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT)
- {
- gchar *default_name = g_strdup_printf("default-%s", row->name);
+ gchar *kf_key = g_strconcat (key,
+ " " DBUS_TYPE_STRING_AS_STRING, NULL);
+ g_key_file_set_string (keyfile, group_name, kf_key,
+ g_value_get_string (val));
+ g_free (kf_key);
+ break;
+ }
- switch (row->gtype)
- {
- case G_TYPE_STRING:
- g_key_file_set_string(f, section_name, default_name,
- row->def);
- break;
- case G_TYPE_INT:
- case G_TYPE_UINT:
- g_key_file_set_integer(f, section_name, default_name,
- GPOINTER_TO_INT(row->def));
- break;
- case G_TYPE_BOOLEAN:
- g_key_file_set_boolean(f, section_name, default_name,
- GPOINTER_TO_INT(row->def) ? 1 : 0);
- }
- g_free(default_name);
+ case G_TYPE_UINT:
+ {
+ gchar *kf_key = g_strconcat (key,
+ " " DBUS_TYPE_UINT32_AS_STRING, NULL);
+ gchar *kf_val = g_strdup_printf ("%u", g_value_get_uint (val));
+ g_key_file_set_value (keyfile, group_name, kf_key, kf_val);
+ g_free (kf_key);
+ g_free (kf_val);
+ break;
+ }
+
+ /* FIXME: when we depend on Glib 2.26, we can use
+ * g_key_file_set_[u]int64 (g.o #614864). */
+ case G_TYPE_UINT64:
+ {
+ gchar *kf_key = g_strconcat (key,
+ " " DBUS_TYPE_UINT64_AS_STRING, NULL);
+ gchar *kf_val = g_strdup_printf ("%" G_GUINT64_FORMAT,
+ g_value_get_uint64 (val));
+ g_key_file_set_value (keyfile, group_name, kf_key, kf_val);
+ g_free (kf_key);
+ g_free (kf_val);
+ break;
+ }
+
+ case G_TYPE_INT:
+ {
+ gchar *kf_key = g_strconcat (key,
+ " " DBUS_TYPE_INT32_AS_STRING, NULL);
+ g_key_file_set_integer (keyfile, group_name, kf_key,
+ g_value_get_int (val));
+ g_free (kf_key);
+ break;
+ }
+
+ case G_TYPE_INT64:
+ {
+ gchar *kf_key = g_strconcat (key,
+ " " DBUS_TYPE_UINT64_AS_STRING, NULL);
+ gchar *kf_val = g_strdup_printf ("%" G_GINT64_FORMAT,
+ g_value_get_int64 (val));
+ g_key_file_set_value (keyfile, group_name, kf_key, kf_val);
+ g_free (kf_key);
+ g_free (kf_val);
+ break;
+ }
+
+ default:
+ {
+ if (G_VALUE_TYPE (val) == G_TYPE_STRV)
+ {
+ gchar **list = g_value_get_boxed (val);
+ gchar *kf_key = g_strconcat (key, " "
+ DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING, NULL);
+ g_key_file_set_string_list (keyfile, group_name,
+ kf_key, (const gchar **) list, g_strv_length (list));
+ g_free (kf_key);
+ break;
}
+
+ /* we'd rather crash than forget to write required rcc property */
+ g_assert_not_reached ();
}
- g_free(section_name);
}
- return g_key_file_to_data(f, NULL, error);
}
-/* defined by telepathy-glib if your version is new enough - included here
- * so telepathy-glib 0.5.4 and 0.5.5 will still work
- */
-#ifndef TP_CM_BUS_NAME_BASE
-# define TP_CM_BUS_NAME_BASE "org.freedesktop.Telepathy.ConnectionManager."
-# define TP_CM_OBJECT_PATH_BASE "/org/freedesktop/Telepathy/ConnectionManager/"
-#endif
+static gchar *
+generate_group_name (GHashTable *props)
+{
+ static guint counter = 0;
+ gchar *retval;
+ gchar *chan_type = g_ascii_strdown (tp_asv_get_string (props,
+ TP_PROP_CHANNEL_CHANNEL_TYPE), -1);
+ gchar *chan_type_suffix;
+ gchar *handle_type_name;
+ guint handle_type = tp_asv_get_uint32 (props,
+ TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL);
+
+ g_assert (chan_type != NULL);
+ chan_type_suffix = strrchr (chan_type, '.');
+ g_assert (chan_type_suffix != NULL);
+ chan_type_suffix++;
+
+ switch (handle_type)
+ {
+ case TP_HANDLE_TYPE_CONTACT:
+ handle_type_name = "-1on1";
+ break;
+
+ case TP_HANDLE_TYPE_ROOM:
+ handle_type_name = "-multi";
+ break;
+
+ case TP_HANDLE_TYPE_GROUP:
+ handle_type_name = "-group";
+ break;
+
+ case TP_HANDLE_TYPE_LIST:
+ handle_type_name = "-list";
+ break;
+
+ default:
+ handle_type_name = "";
+ }
+
+ retval = g_strdup_printf ("%s%s-%d", chan_type_suffix, handle_type_name,
+ ++counter);
+
+ g_free (chan_type);
+ return retval;
+}
+
+static void
+write_rccs (GKeyFile *f, const gchar *section_name, GHashTable *props)
+{
+ GPtrArray *rcc_list = tp_asv_get_boxed (props,
+ TP_PROP_PROTOCOL_REQUESTABLE_CHANNEL_CLASSES,
+ TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST);
+ guint i;
+ gchar **group_names = g_new0 (gchar *, rcc_list->len + 1);
+
+ for (i = 0; i < rcc_list->len; i++)
+ {
+ gchar **allowed;
+ gchar *group_name;
+ GHashTable *fixed;
+ GHashTableIter iter;
+ gpointer k, v;
+
+ tp_value_array_unpack (g_ptr_array_index (rcc_list, i), 2,
+ &fixed, &allowed);
+
+ group_name = generate_group_name (fixed);
+
+ g_hash_table_iter_init (&iter, fixed);
+ while (g_hash_table_iter_next (&iter, &k, &v))
+ {
+ const gchar *key = k;
+ GValue *val = v;
+
+ write_rcc_property (f, group_name, key, val);
+ }
+
+ /* takes ownership */
+ group_names[i] = group_name;
+
+ g_key_file_set_string_list (f, group_name, "allowed",
+ (const gchar **) allowed, g_strv_length (allowed));
+ }
+
+ g_key_file_set_string_list (f, section_name, "RequestableChannelClasses",
+ (const gchar **) group_names, rcc_list->len);
+
+ g_strfreev (group_names);
+}
+
+static gchar *
+mgr_file_contents (const char *busname,
+ const char *objpath,
+ GSList *protocols,
+ GError **error)
+{
+ GKeyFile *f = g_key_file_new ();
+ gchar *file_data;
+
+ g_key_file_set_string (f, "ConnectionManager", "BusName", busname);
+ g_key_file_set_string (f, "ConnectionManager", "ObjectPath", objpath);
+
+ /* there are no CM interfaces defined yet, so we cheat */
+ g_key_file_set_string (f, "ConnectionManager", "Interfaces", "");
+
+ while (protocols != NULL)
+ {
+ TpBaseProtocol *protocol = protocols->data;
+ GHashTable *props =
+ tp_base_protocol_get_immutable_properties (protocol);
+ gchar *section_name = g_strdup_printf ("Protocol %s",
+ tp_base_protocol_get_name (protocol));
+ const gchar * const *ifaces = tp_asv_get_strv (props,
+ TP_PROP_PROTOCOL_INTERFACES);
+ const gchar * const *c_ifaces = tp_asv_get_strv (props,
+ TP_PROP_PROTOCOL_CONNECTION_INTERFACES);
+
+ write_parameters (f, section_name, protocol);
+ write_rccs (f, section_name, props);
+
+ g_key_file_set_string_list (f, section_name, "Interfaces",
+ ifaces, g_strv_length ((gchar **) ifaces));
+ g_key_file_set_string_list (f, section_name, "ConnectionInterfaces",
+ c_ifaces, g_strv_length ((gchar **) c_ifaces));
+
+ WRITE_STR (TP_PROP_PROTOCOL_VCARD_FIELD, "VCardField");
+ WRITE_STR (TP_PROP_PROTOCOL_ENGLISH_NAME, "EnglishName");
+ WRITE_STR (TP_PROP_PROTOCOL_ICON, "Icon");
+
+ g_free (section_name);
+ g_hash_table_destroy (props);
+ protocols = protocols->next;
+ }
+
+ file_data = g_key_file_to_data (f, NULL, error);
+ g_key_file_free (f);
+ return file_data;
+}
int
main (void)
{
GError *error = NULL;
+ gchar *s;
+ GSList *protocols = NULL;
+
+ g_type_init ();
+ dbus_g_type_specialized_init ();
+
+ protocols = g_slist_prepend (protocols,
+ tpsip_protocol_new (NULL));
+
+ s = mgr_file_contents (TP_CM_BUS_NAME_BASE "sofiasip",
+ TP_CM_OBJECT_PATH_BASE "sofiasip",
+ protocols, &error);
+
+ g_object_unref (protocols->data);
+ g_slist_free (protocols);
- gchar *s = mgr_file_contents(TP_CM_BUS_NAME_BASE "sofiasip",
- TP_CM_OBJECT_PATH_BASE "sofiasip",
- tpsip_protocols, &error);
if (!s)
{
- fprintf(stderr, "%s\n", error->message);
- g_error_free(error);
+ fprintf (stderr, "%s", error->message);
+ g_error_free (error);
return 1;
}
- printf("%s", s);
- g_free(s);
+ printf ("%s", s);
+ g_free (s);
return 0;
}