telepathy-cauchy/src/cauchy-connection.c

441 lines
13 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* This file is part of telepathy-cauchy
*
* telepathy-cauchy 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 3 of the * License, or (at your option) any later
* version.
*
* telepathy-cauchy 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 telepathy-cauchy. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "cauchy-connection.h"
#include "cauchy-contact-info.h"
static void _aliasing_iface_init(gpointer, gpointer);
struct _CauchyConnectionPrivate {
gchar *cauchy_id;
gchar *homeserver;
gchar *password;
GHashTable *aliases;
gboolean dispose_has_run;
TpSimplePasswordManager *password_manager;
};
enum {
PROP_0,
PROP_CAUCHY_ID,
PROP_HOMESERVER,
PROP_PASSWORD,
PROP_COUNT
};
static const gchar *interfaces_always_present[] = {
TP_IFACE_CONNECTION_INTERFACE_ALIASING,
TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO,
/* TODO:
CAUCHY_IFACE_CONNECTION_INTERFACE_RENAMING,
*/
TP_IFACE_CONNECTION_INTERFACE_REQUESTS,
TP_IFACE_CONNECTION_INTERFACE_CONTACTS,
NULL
};
G_DEFINE_TYPE_WITH_CODE(
CauchyConnection, cauchy_connection, TP_TYPE_BASE_CONNECTION,
G_IMPLEMENT_INTERFACE(
TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING,
_aliasing_iface_init);
G_IMPLEMENT_INTERFACE(
TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_INFO,
cauchy_contact_info_iface_init);
/* TODO:
G_IMPLEMENT_INTERFACE(
CAUCHY_TYPE_SVC_CONNECTION_INTERFACE_RENAMING,
_renaming_interface_init);
*/
G_IMPLEMENT_INTERFACE(
TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACTS,
tp_contacts_mixin_iface_init);
);
static void
cauchy_connection_set_property(GObject *obj,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
CauchyConnection *connection = CAUCHY_CONNECTION(obj);
CauchyConnectionPrivate *priv = connection->priv;
switch (prop_id) {
case PROP_CAUCHY_ID:
g_free(priv->cauchy_id);
priv->cauchy_id = g_value_dup_string(value);
break;
case PROP_HOMESERVER:
g_free(priv->homeserver);
priv->homeserver = g_value_dup_string(value);
break;
case PROP_PASSWORD:
g_free(priv->password);
priv->password = g_value_dup_string(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, pspec);
break;
}
}
static void
cauchy_connection_get_property(GObject *obj,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
CauchyConnection *connection = CAUCHY_CONNECTION(obj);
CauchyConnectionPrivate *priv = connection->priv;
switch (prop_id) {
case PROP_CAUCHY_ID:
g_value_set_string(value, priv->cauchy_id);
break;
case PROP_HOMESERVER:
g_value_set_string(value, priv->homeserver);
break;
case PROP_PASSWORD:
g_value_set_string(value, priv->password);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, pspec);
break;
}
}
static void
cauchy_connection_get_alias_flags(TpSvcConnectionInterfaceAliasing *iface,
DBusGMethodInvocation *context)
{
tp_svc_connection_interface_aliasing_return_from_get_alias_flags(context, 0);
}
static const gchar *
gimme_an_alias(CauchyConnection *connection,
TpHandleRepoIface *repo,
TpHandle handle)
{
const gchar *alias = g_hash_table_lookup(connection->priv->aliases,
GUINT_TO_POINTER(handle));
if (alias != NULL) {
return alias;
} else {
return tp_handle_inspect(repo, handle);
}
}
static void
cauchy_connection_get_aliases(TpSvcConnectionInterfaceAliasing *iface,
const GArray *handles,
DBusGMethodInvocation *context)
{
CauchyConnection *self = CAUCHY_CONNECTION(iface);
TpHandleRepoIface *repo = tp_base_connection_get_handles(
TP_BASE_CONNECTION(iface),
TP_HANDLE_TYPE_CONTACT);
GError *err = NULL;
GHashTable *aliases;
if (!tp_handles_are_valid(repo, handles, FALSE, &err)) {
dbus_g_method_return_error(context, err);
g_error_free(err);
return;
}
aliases = g_hash_table_new(NULL, NULL);
for (guint i = 0; i < handles->len; i++) {
TpHandle handle = g_array_index(handles, TpHandle, i);
g_hash_table_insert(aliases,
GUINT_TO_POINTER(handle),
(gpointer)gimme_an_alias(self, repo, handle));
}
tp_svc_connection_interface_aliasing_return_from_get_aliases(context, aliases);
g_hash_table_unref(aliases);
}
static void
cauchy_connection_request_aliases(TpSvcConnectionInterfaceAliasing *iface,
const GArray *handles,
DBusGMethodInvocation *context)
{
CauchyConnection *connection = CAUCHY_CONNECTION(iface);
TpHandleRepoIface *repo = tp_base_connection_get_handles(
TP_BASE_CONNECTION(iface), TP_HANDLE_TYPE_CONTACT);
GError *err = NULL;
const gchar **aliases;
if (!tp_handles_are_valid(repo, handles, FALSE, &err)) {
dbus_g_method_return_error(context, err);
g_error_free(err);
return;
}
aliases = g_new0(const gchar *, handles->len + 1);
for (guint i = 0; i < handles->len; i++) {
TpHandle handle = g_array_index(handles, TpHandle, i);
aliases[i] = gimme_an_alias(connection, repo, handle);
}
tp_svc_connection_interface_aliasing_return_from_request_aliases(context, aliases);
g_free(aliases);
}
static void
_aliasing_iface_init(gpointer g_iface, gpointer iface_data)
{
TpSvcConnectionInterfaceAliasingClass *klass = (TpSvcConnectionInterfaceAliasingClass *)g_iface;
#define IMPLEMENT(x) tp_svc_connection_interface_aliasing_implement_##x(klass, cauchy_connection_##x)
IMPLEMENT(get_alias_flags);
IMPLEMENT(get_aliases);
IMPLEMENT(request_aliases);
#undef IMPLEMENT
}
static void
cauchy_connection_finalize(GObject *gobject)
{
g_signal_handlers_destroy(gobject);
G_OBJECT_CLASS(cauchy_connection_parent_class)->finalize(gobject);
}
static void
_aliasing_fill_contact_attributes(GObject *obj,
const GArray *contacts,
GHashTable *attributes_hash)
{
CauchyConnection *connection = CAUCHY_CONNECTION(obj);
TpHandleRepoIface *repo = tp_base_connection_get_handles(
TP_BASE_CONNECTION(connection),
TP_HANDLE_TYPE_CONTACT);
for (guint i = 0; i < contacts->len; i++) {
TpHandle handle = g_array_index(contacts, TpHandle, i);
const gchar *alias = gimme_an_alias(connection, repo, handle);
g_assert(alias != NULL);
tp_contacts_mixin_set_contact_attribute(
attributes_hash,
handle,
TP_IFACE_CONNECTION_INTERFACE_ALIASING"/alias",
tp_g_value_slice_new_string(alias));
}
}
static void
cauchy_connection_constructed(GObject *obj)
{
CauchyConnection *connection = CAUCHY_CONNECTION(obj);
cauchy_contact_info_init(connection);
tp_contacts_mixin_add_contact_attributes_iface(
obj,
TP_IFACE_CONNECTION_INTERFACE_ALIASING,
_aliasing_fill_contact_attributes);
}
static void
cauchy_connection_dispose(GObject *obj)
{
CauchyConnection *connection = CAUCHY_CONNECTION(obj);
CauchyConnectionPrivate *priv = connection->priv;
if (priv->dispose_has_run) {
return;
}
priv->dispose_has_run = TRUE;
tp_clear_pointer(&priv->aliases, g_hash_table_unref);
if (G_OBJECT_CLASS(cauchy_connection_parent_class)->dispose) {
G_OBJECT_CLASS(cauchy_connection_parent_class)->dispose(obj);
}
}
static void
_iface_create_handle_repos(TpBaseConnection *connection,
TpHandleRepoIface **repos)
{
for (int i = 0; i < NUM_TP_HANDLE_TYPES; i++) {
repos[i] = NULL;
}
// TODO cauchy_handle_repos_init(repos);
}
static gchar *
_iface_get_unique_connection_name(TpBaseConnection *base)
{
CauchyConnection *connection = CAUCHY_CONNECTION(base);
CauchyConnectionPrivate *priv = connection->priv;
return g_strdup_printf(
"@%s:%s%p",
priv->cauchy_id, priv->homeserver, connection);
}
static GPtrArray *
_iface_create_channel_managers(TpBaseConnection *base)
{
CauchyConnection *connection = CAUCHY_CONNECTION(base);
CauchyConnectionPrivate *priv = connection->priv;
GPtrArray *managers = g_ptr_array_sized_new(1);
//GObject *manager;
/* TODO:
manager = g_object_new(CAUCHY_TYPE_IM_MANAGER,
"connection", connection,
NULL);
g_ptr_array_add(managers, manager);
manager = g_object_new(CAUCHY_TYPE_IM_MUC_MANAGER,
"connection", connection,
NULL);
*/
priv->password_manager = tp_simple_password_manager_new(base);
g_ptr_array_add(managers, priv->password_manager);
/* TODO:
manager = g_object_new(CAUCHY_TYPE_ROOMLIST_MANAGER,
"connection", connection,
NULL);
g_ptr_array_add(managers, manager);
priv->tls_manager = g_object_new(IDLE_TYPE_SERVER_TLS_MANAGER,
"connection", connection,
NULL);
g_ptr_array_add(managers, manager);
*/
return managers;
}
static void
_iface_disconnected(TpBaseConnection *base)
{}
static void
cauchy_connection_class_init(CauchyConnectionClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
TpBaseConnectionClass *parent_class = TP_BASE_CONNECTION_CLASS(klass);
GParamSpec *param_spec;
g_type_class_add_private(klass, sizeof(CauchyConnectionPrivate));
gobject_class->constructed = cauchy_connection_constructed;
gobject_class->set_property = cauchy_connection_set_property;
gobject_class->get_property = cauchy_connection_get_property;
gobject_class->dispose = cauchy_connection_dispose;
gobject_class->finalize = cauchy_connection_finalize;
parent_class->create_handle_repos = _iface_create_handle_repos;
parent_class->get_unique_connection_name = _iface_get_unique_connection_name;
parent_class->create_channel_factories = NULL;
parent_class->create_channel_managers = _iface_create_channel_managers;
parent_class->connecting = NULL;
parent_class->connected = NULL;
parent_class->disconnected = _iface_disconnected;
/* TODO:
parent_class->shut_down = _iface_shut_down;
parent_class->start_connecting = _iface_start_connecting;
parent_class->get_interfaces_always_present = get_interfaces_always_present;
*/
param_spec = g_param_spec_string(
"cauchy-id",
"Cauchy ID",
"Your registered Cauchy ID",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property(gobject_class, PROP_CAUCHY_ID, param_spec);
param_spec = g_param_spec_string(
"homeserver",
"Homeserver",
"The home server to connect to",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property(gobject_class, PROP_HOMESERVER, param_spec);
param_spec = g_param_spec_string(
"password",
"Password",
"Password to authenticate to the server with",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property(gobject_class, PROP_PASSWORD, param_spec);
tp_contacts_mixin_class_init(gobject_class, G_STRUCT_OFFSET(CauchyConnectionClass, contacts));
cauchy_contact_info_class_init(klass);
}
static void
cauchy_connection_init(CauchyConnection *connection)
{
CauchyConnectionPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE(
connection,
CAUCHY_TYPE_CONNECTION, CauchyConnectionPrivate);
connection->priv = priv;
priv->aliases = g_hash_table_new_full(NULL, NULL, NULL, g_free);
tp_contacts_mixin_init(
G_OBJECT(connection),
G_STRUCT_OFFSET(CauchyConnection, contacts));
tp_base_connection_register_with_contacts_mixin(
(TpBaseConnection *)connection);
}
const gchar * const *
cauchy_connection_get_implemented_interfaces(void)
{
/* We dont have any conditionally implemented interfaces */
return interfaces_always_present;
}