telepathy: add contact search channel
[siplcs.git] / src / telepathy / telepathy-connection.c
blob13b9655e19a3d2852d9b8bc5e74fffcc8819963c
1 /**
2 * @file telepathy-connection.c
4 * pidgin-sipe
6 * Copyright (C) 2012 SIPE Project <http://sipe.sourceforge.net/>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
27 #include <string.h>
29 #include <glib-object.h>
30 #include <telepathy-glib/base-connection.h>
31 #include <telepathy-glib/base-protocol.h>
32 #include <telepathy-glib/contacts-mixin.h>
33 #include <telepathy-glib/handle-repo-dynamic.h>
34 #include <telepathy-glib/presence-mixin.h>
35 #include <telepathy-glib/simple-password-manager.h>
36 #include <telepathy-glib/telepathy-glib.h>
38 #include "sipe-backend.h"
39 #include "sipe-common.h"
40 #include "sipe-core.h"
42 #include "telepathy-private.h"
44 G_BEGIN_DECLS
46 * Connection class - data structures
48 typedef struct _SipeConnectionClass {
49 TpBaseConnectionClass parent_class;
50 TpContactsMixinClass contacts_mixin;
51 TpPresenceMixinClass presence_mixin;
52 } SipeConnectionClass;
54 typedef struct _SipeConnection {
55 TpBaseConnection parent;
56 TpContactsMixinClass contacts_mixin;
57 TpPresenceMixin presence_mixin;
59 /* channel managers */
60 TpSimplePasswordManager *password_manager;
61 struct _SipeContactList *contact_list;
63 struct sipe_backend_private private;
64 gchar *account;
65 gchar *login;
66 gchar *password;
67 gchar *server;
68 gchar *port;
69 guint transport;
70 gchar *user_agent;
71 gchar *authentication;
72 gboolean is_disconnecting;
73 } SipeConnection;
75 #define SIPE_PUBLIC_TO_CONNECTION sipe_public->backend_private->connection
78 * Connection class - type macros
80 static GType sipe_connection_get_type(void) G_GNUC_CONST;
81 #define SIPE_TYPE_CONNECTION \
82 (sipe_connection_get_type())
83 #define SIPE_CONNECTION(obj) \
84 (G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_CONNECTION, \
85 SipeConnection))
86 G_END_DECLS
89 * Connection class - type definition
91 static void init_aliasing (gpointer, gpointer);
92 G_DEFINE_TYPE_WITH_CODE(SipeConnection,
93 sipe_connection,
94 TP_TYPE_BASE_CONNECTION,
95 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING,
96 init_aliasing);
97 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACTS,
98 tp_contacts_mixin_iface_init);
99 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_GROUPS,
100 tp_base_contact_list_mixin_groups_iface_init);
101 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_LIST,
102 tp_base_contact_list_mixin_list_iface_init);
103 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_PRESENCE,
104 tp_presence_mixin_iface_init);
105 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_SIMPLE_PRESENCE,
106 tp_presence_mixin_simple_presence_iface_init)
111 * Connection class - instance methods
113 static gchar *normalize_contact(SIPE_UNUSED_PARAMETER TpHandleRepoIface *repo,
114 const gchar *id,
115 SIPE_UNUSED_PARAMETER gpointer context,
116 GError **error)
118 return(sipe_telepathy_protocol_normalize_contact(NULL, id, error));
121 static void create_handle_repos(SIPE_UNUSED_PARAMETER TpBaseConnection *conn,
122 TpHandleRepoIface *repos[NUM_TP_HANDLE_TYPES])
124 repos[TP_HANDLE_TYPE_CONTACT] = tp_dynamic_handle_repo_new(TP_HANDLE_TYPE_CONTACT,
125 normalize_contact,
126 NULL);
129 static gboolean connect_to_core(SipeConnection *self,
130 GError **error)
132 gchar *login_domain = NULL;
133 gchar *login_account = NULL;
134 struct sipe_core_public *sipe_public;
135 const gchar *errmsg;
137 /* login name specified? */
138 if (self->login && strlen(self->login)) {
139 /* Allowed domain-account separators are / or \ */
140 gchar **domain_user = g_strsplit_set(self->login, "/\\", 2);
141 gboolean has_domain = domain_user[1] != NULL;
142 SIPE_DEBUG_INFO("connect_to_core: login '%s'", self->login);
143 login_domain = has_domain ? g_strdup(domain_user[0]) : NULL;
144 login_account = g_strdup(domain_user[has_domain ? 1 : 0]);
145 SIPE_DEBUG_INFO("connect_to_core: auth domain '%s' user '%s'",
146 login_domain ? login_domain : "",
147 login_account);
148 g_strfreev(domain_user);
151 sipe_public = sipe_core_allocate(self->account,
152 login_domain, login_account,
153 self->password,
154 NULL, /* @TODO: email */
155 NULL, /* @TODO: email_url */
156 &errmsg);
157 g_free(login_domain);
158 g_free(login_account);
160 SIPE_DEBUG_INFO("connect_to_core: created %p", sipe_public);
162 if (sipe_public) {
163 struct sipe_backend_private *telepathy_private = &self->private;
165 /* initialize backend private data */
166 sipe_public->backend_private = telepathy_private;
167 telepathy_private->public = sipe_public;
168 telepathy_private->contact_list = self->contact_list;
169 telepathy_private->connection = self;
170 telepathy_private->activity = SIPE_ACTIVITY_UNSET;
171 telepathy_private->message = NULL;
172 telepathy_private->transport = NULL;
173 telepathy_private->ipaddress = NULL;
175 /* map option list to flags - default is NTLM */
176 SIPE_CORE_FLAG_UNSET(KRB5);
177 SIPE_CORE_FLAG_UNSET(TLS_DSK);
178 #ifdef HAVE_LIBKRB5
179 if (sipe_strequal(self->authentication, "krb5")) {
180 SIPE_DEBUG_INFO_NOFORMAT("connect_to_core: KRB5 selected");
181 SIPE_CORE_FLAG_SET(KRB5);
182 } else
183 #endif
184 if (sipe_strequal(self->authentication, "tls-dsk")) {
185 SIPE_DEBUG_INFO_NOFORMAT("connect_to_core: TLS-DSK selected");
186 SIPE_CORE_FLAG_SET(TLS_DSK);
189 /* @TODO: add parameter for SSO */
190 SIPE_CORE_FLAG_UNSET(SSO);
192 sipe_core_transport_sip_connect(sipe_public,
193 self->transport,
194 self->server,
195 self->port);
197 return(TRUE);
198 } else {
199 g_set_error_literal(error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
200 errmsg);
201 return(FALSE);
205 static void password_manager_cb(GObject *source,
206 GAsyncResult *result,
207 gpointer data)
209 SipeConnection *self = data;
210 TpBaseConnection *base = TP_BASE_CONNECTION(self);
211 GError *error = NULL;
212 const GString *password = tp_simple_password_manager_prompt_finish(
213 TP_SIMPLE_PASSWORD_MANAGER(source),
214 result,
215 &error);
217 if (password == NULL) {
218 SIPE_DEBUG_ERROR("password_manager_cb: failed: %s",
219 error ? error->message : "UNKNOWN");
221 if (base->status != TP_CONNECTION_STATUS_DISCONNECTED) {
222 tp_base_connection_disconnect_with_dbus_error(base,
223 error ? tp_error_get_dbus_name(error->code) : "",
224 NULL,
225 TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED);
227 g_error_free(error);
228 } else {
230 g_free(self->password);
231 self->password = g_strdup(password->str);
233 if (!connect_to_core(self, &error)) {
234 if (base->status != TP_CONNECTION_STATUS_DISCONNECTED) {
235 tp_base_connection_disconnect_with_dbus_error(base,
236 tp_error_get_dbus_name(error->code),
237 NULL,
238 TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED);
240 g_error_free(error);
245 static gboolean start_connecting(TpBaseConnection *base,
246 GError **error)
248 SipeConnection *self = SIPE_CONNECTION(base);
249 gboolean rc = TRUE;
250 gchar *uri = sipe_telepathy_protocol_normalize_contact(NULL,
251 self->account,
252 error);
254 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::start_connecting");
256 /* set up mandatory self-handle */
257 if (uri) {
258 base->self_handle = tp_handle_ensure(tp_base_connection_get_handles(base,
259 TP_HANDLE_TYPE_CONTACT),
260 uri,
261 NULL,
262 error);
263 g_free(uri);
264 if (!base->self_handle) {
265 SIPE_DEBUG_ERROR("SipeConnection::start_connecting: self handle creation failed: %s",
266 (*error)->message);
267 return(FALSE);
269 } else {
270 SIPE_DEBUG_ERROR("SipeConnection::start_connecting: %s",
271 (*error)->message);
272 return(FALSE);
275 tp_base_connection_change_status(base, TP_CONNECTION_STATUS_CONNECTING,
276 TP_CONNECTION_STATUS_REASON_REQUESTED);
278 /* we need a password */
279 if (self->password)
280 rc = connect_to_core(self, error);
281 else {
282 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::start_connecting: requesting password from user");
283 tp_simple_password_manager_prompt_async(self->password_manager,
284 password_manager_cb,
285 self);
288 return(rc);
291 static gboolean disconnect_from_core(gpointer data)
293 TpBaseConnection *base = data;
294 SipeConnection *self = SIPE_CONNECTION(base);
295 struct sipe_backend_private *telepathy_private = &self->private;
296 struct sipe_core_public *sipe_public = telepathy_private->public;
298 SIPE_DEBUG_INFO("disconnect_from_core: %p", sipe_public);
300 if (sipe_public)
301 sipe_core_deallocate(sipe_public);
302 telepathy_private->public = NULL;
303 telepathy_private->transport = NULL;
305 g_free(telepathy_private->ipaddress);
306 telepathy_private->ipaddress = NULL;
308 g_free(telepathy_private->message);
309 telepathy_private->message = NULL;
311 SIPE_DEBUG_INFO_NOFORMAT("disconnect_from_core: core deallocated");
313 /* now it is OK to destroy the connection object */
314 tp_base_connection_finish_shutdown(base);
316 return(FALSE);
319 static void shut_down(TpBaseConnection *base)
321 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::shut_down");
323 /* this can be called synchronously, defer destruction */
324 g_idle_add(disconnect_from_core, base);
327 static GPtrArray *create_channel_managers(TpBaseConnection *base)
329 SipeConnection *self = SIPE_CONNECTION(base);
330 GPtrArray *channel_managers = g_ptr_array_new();
332 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::create_channel_managers");
334 self->contact_list = sipe_telepathy_contact_list_new(base);
335 g_ptr_array_add(channel_managers, self->contact_list);
337 self->password_manager = tp_simple_password_manager_new(base);
338 g_ptr_array_add(channel_managers, self->password_manager);
340 g_ptr_array_add(channel_managers, sipe_telepathy_search_new(base));
342 return(channel_managers);
345 static void aliasing_fill_contact_attributes(GObject *object,
346 const GArray *contacts,
347 GHashTable *attributes)
349 SipeConnection *self = SIPE_CONNECTION(object);
350 guint i;
352 for (i = 0; i < contacts->len; i++) {
353 TpHandle contact = g_array_index(contacts, guint, i);
355 tp_contacts_mixin_set_contact_attribute(attributes,
356 contact,
357 TP_TOKEN_CONNECTION_INTERFACE_ALIASING_ALIAS,
358 tp_g_value_slice_new_string(
359 sipe_telepathy_buddy_get_alias(self->contact_list,
360 contact)));
364 static void sipe_connection_constructed(GObject *object)
366 TpBaseConnection *base = TP_BASE_CONNECTION(object);
367 void (*chain_up)(GObject *) = G_OBJECT_CLASS(sipe_connection_parent_class)->constructed;
369 if (chain_up)
370 chain_up(object);
372 tp_contacts_mixin_init(object,
373 G_STRUCT_OFFSET(SipeConnection, contacts_mixin));
374 tp_base_connection_register_with_contacts_mixin(base);
376 tp_base_contact_list_mixin_register_with_contacts_mixin(base);
378 tp_contacts_mixin_add_contact_attributes_iface(object,
379 TP_IFACE_CONNECTION_INTERFACE_ALIASING,
380 aliasing_fill_contact_attributes);
382 tp_presence_mixin_init(object,
383 G_STRUCT_OFFSET(SipeConnection,
384 presence_mixin));
385 tp_presence_mixin_simple_presence_register_with_contacts_mixin(object);
388 static void sipe_connection_finalize(GObject *object)
390 SipeConnection *self = SIPE_CONNECTION(object);
392 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::finalize");
394 tp_contacts_mixin_finalize(object);
396 g_free(self->authentication);
397 g_free(self->user_agent);
398 g_free(self->port);
399 g_free(self->server);
400 g_free(self->password);
401 g_free(self->login);
402 g_free(self->account);
404 G_OBJECT_CLASS(sipe_connection_parent_class)->finalize(object);
408 * Connection class - type implementation
410 static const gchar *interfaces_always_present[] = {
411 /* @TODO */
412 TP_IFACE_CONNECTION_INTERFACE_ALIASING,
413 TP_IFACE_CONNECTION_INTERFACE_CONTACT_GROUPS,
414 TP_IFACE_CONNECTION_INTERFACE_CONTACT_LIST,
415 TP_IFACE_CONNECTION_INTERFACE_CONTACTS,
416 TP_IFACE_CONNECTION_INTERFACE_PRESENCE,
417 TP_IFACE_CONNECTION_INTERFACE_REQUESTS,
418 TP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE,
419 NULL
422 static void sipe_connection_class_init(SipeConnectionClass *klass)
424 GObjectClass *object_class = G_OBJECT_CLASS(klass);
425 TpBaseConnectionClass *base_class = TP_BASE_CONNECTION_CLASS(klass);
427 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::class_init");
429 object_class->constructed = sipe_connection_constructed;
430 object_class->finalize = sipe_connection_finalize;
432 base_class->create_handle_repos = create_handle_repos;
433 base_class->start_connecting = start_connecting;
434 base_class->shut_down = shut_down;
435 base_class->create_channel_managers = create_channel_managers;
437 base_class->interfaces_always_present = interfaces_always_present;
439 tp_contacts_mixin_class_init(object_class,
440 G_STRUCT_OFFSET(SipeConnectionClass,
441 contacts_mixin));
442 sipe_telepathy_status_init(object_class,
443 G_STRUCT_OFFSET(SipeConnectionClass,
444 presence_mixin));
445 tp_presence_mixin_simple_presence_init_dbus_properties(object_class);
446 tp_base_contact_list_mixin_class_init(base_class);
449 static void sipe_connection_init(SIPE_UNUSED_PARAMETER SipeConnection *self)
451 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::init");
455 * Connection class - interface implementation
457 * Contact aliases
459 static void get_alias_flags(TpSvcConnectionInterfaceAliasing *aliasing,
460 DBusGMethodInvocation *context)
462 TpBaseConnection *base = TP_BASE_CONNECTION(aliasing);
464 TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED(base, context);
465 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::get_alias_flags called");
467 tp_svc_connection_interface_aliasing_return_from_get_alias_flags(context,
468 TP_CONNECTION_ALIAS_FLAG_USER_SET);
471 static void get_aliases(TpSvcConnectionInterfaceAliasing *aliasing,
472 const GArray *contacts,
473 DBusGMethodInvocation *context)
475 SipeConnection *self = SIPE_CONNECTION(aliasing);
476 TpBaseConnection *base = TP_BASE_CONNECTION(aliasing);
477 TpHandleRepoIface *contact_repo = tp_base_connection_get_handles(base,
478 TP_HANDLE_TYPE_CONTACT);
479 GError *error = NULL;
480 GHashTable *result;
481 guint i;
483 TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED(base, context);
484 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::get_aliases called");
486 if (!tp_handles_are_valid(contact_repo, contacts, FALSE, &error)) {
487 dbus_g_method_return_error(context, error);
488 g_error_free(error);
489 return;
492 result = g_hash_table_new(g_direct_hash, g_direct_equal);
494 for (i = 0; i < contacts->len; i++) {
495 TpHandle contact = g_array_index(contacts, TpHandle, i);
496 const gchar *alias = sipe_telepathy_buddy_get_alias(self->contact_list,
497 contact);
498 g_hash_table_insert(result,
499 GUINT_TO_POINTER(contact),
500 (gchar *) alias);
503 tp_svc_connection_interface_aliasing_return_from_get_aliases(context,
504 result);
505 g_hash_table_unref(result);
508 static void request_aliases(TpSvcConnectionInterfaceAliasing *aliasing,
509 const GArray *contacts,
510 DBusGMethodInvocation *context)
512 SipeConnection *self = SIPE_CONNECTION(aliasing);
513 TpBaseConnection *base = TP_BASE_CONNECTION(aliasing);
514 TpHandleRepoIface *contact_repo = tp_base_connection_get_handles(base,
515 TP_HANDLE_TYPE_CONTACT);
516 GError *error = NULL;
517 GPtrArray *result;
518 gchar **strings;
519 guint i;
521 TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED(base, context);
522 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::request_aliases called");
524 if (!tp_handles_are_valid(contact_repo, contacts, FALSE, &error)) {
525 dbus_g_method_return_error(context, error);
526 g_error_free(error);
527 return;
530 result = g_ptr_array_sized_new(contacts->len + 1);
532 for (i = 0; i < contacts->len; i++) {
533 TpHandle contact = g_array_index(contacts, TpHandle, i);
534 const gchar *alias = sipe_telepathy_buddy_get_alias(self->contact_list,
535 contact);
536 g_ptr_array_add(result, (gchar *) alias);
539 g_ptr_array_add(result, NULL);
540 strings = (gchar **) g_ptr_array_free(result, FALSE);
542 tp_svc_connection_interface_aliasing_return_from_request_aliases(context,
543 (const gchar **) strings);
544 g_free(strings);
547 static void set_aliases(TpSvcConnectionInterfaceAliasing *aliasing,
548 GHashTable *aliases,
549 DBusGMethodInvocation *context)
551 SipeConnection *self = SIPE_CONNECTION(aliasing);
552 TpBaseConnection *base = TP_BASE_CONNECTION(aliasing);
553 TpHandleRepoIface *contact_repo = tp_base_connection_get_handles(base,
554 TP_HANDLE_TYPE_CONTACT);
555 GHashTableIter iter;
556 gpointer key, value;
558 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::set_aliases called");
560 g_hash_table_iter_init(&iter, aliases);
562 while (g_hash_table_iter_next(&iter, &key, NULL)) {
563 GError *error = NULL;
565 if (!tp_handle_is_valid(contact_repo,
566 GPOINTER_TO_UINT(key),
567 &error)) {
568 dbus_g_method_return_error(context, error);
569 g_error_free(error);
570 return;
574 g_hash_table_iter_init(&iter, aliases);
576 while (g_hash_table_iter_next(&iter, &key, &value)) {
577 sipe_telepathy_buddy_set_alias(self->contact_list,
578 GPOINTER_TO_UINT(key),
579 value);
582 tp_svc_connection_interface_aliasing_return_from_set_aliases(context);
585 static void init_aliasing(gpointer iface,
586 SIPE_UNUSED_PARAMETER gpointer iface_data)
588 TpSvcConnectionInterfaceAliasingClass *klass = iface;
590 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::init_aliasing called");
592 tp_svc_connection_interface_aliasing_implement_get_alias_flags(klass, get_alias_flags);
593 tp_svc_connection_interface_aliasing_implement_request_aliases(klass, request_aliases);
594 tp_svc_connection_interface_aliasing_implement_get_aliases(klass, get_aliases);
595 tp_svc_connection_interface_aliasing_implement_set_aliases(klass, set_aliases);
598 /* create new connection object */
599 TpBaseConnection *sipe_telepathy_connection_new(TpBaseProtocol *protocol,
600 GHashTable *params,
601 SIPE_UNUSED_PARAMETER GError **error)
603 SipeConnection *conn = g_object_new(SIPE_TYPE_CONNECTION,
604 "protocol", tp_base_protocol_get_name(protocol),
605 NULL);
606 const gchar *value;
607 guint port;
608 gboolean valid;
610 SIPE_DEBUG_INFO_NOFORMAT("sipe_telepathy_connection_new");
612 /* initialize private fields */
613 conn->is_disconnecting = FALSE;
615 /* account & login are required fields */
616 conn->account = g_strdup(tp_asv_get_string(params, "account"));
617 conn->login = g_strdup(tp_asv_get_string(params, "login"));
619 /* password */
620 value = tp_asv_get_string(params, "password");
621 if (value && strlen(value))
622 conn->password = g_strdup(value);
623 else
624 conn->password = NULL;
626 /* server name */
627 value = tp_asv_get_string(params, "server");
628 if (value && strlen(value))
629 conn->server = g_strdup(value);
630 else
631 conn->server = NULL;
633 /* server port: core expects a string */
634 port = tp_asv_get_uint32(params, "port", &valid);
635 if (valid)
636 conn->port = g_strdup_printf("%d", port);
637 else
638 conn->port = NULL;
640 /* transport type */
641 value = tp_asv_get_string(params, "transport");
642 if (sipe_strequal(value, "auto")) {
643 conn->transport = conn->server ?
644 SIPE_TRANSPORT_TLS : SIPE_TRANSPORT_AUTO;
645 } else if (sipe_strequal(value, "tls")) {
646 conn->transport = SIPE_TRANSPORT_TLS;
647 } else {
648 conn->transport = SIPE_TRANSPORT_TCP;
651 /* User-Agent: override */
652 value = tp_asv_get_string(params, "useragent");
653 if (value && strlen(value))
654 conn->user_agent = g_strdup(value);
655 else
656 conn->user_agent = NULL;
658 /* authentication type */
659 value = tp_asv_get_string(params, "authentication");
660 if (value && strlen(value) && strcmp(value, "ntlm"))
661 conn->authentication = g_strdup(value);
662 else
663 conn->authentication = NULL; /* NTLM is default */
665 return(TP_BASE_CONNECTION(conn));
668 struct sipe_backend_private *sipe_telepathy_connection_private(GObject *object)
670 SipeConnection *self = SIPE_CONNECTION(object);
671 /* connected to core already? */
672 if (self->private.public)
673 return(&self->private);
674 else
675 return(NULL);
679 * Backend adaptor functions
681 void sipe_backend_connection_completed(struct sipe_core_public *sipe_public)
683 SipeConnection *self = SIPE_PUBLIC_TO_CONNECTION;
684 TpBaseConnection *base = TP_BASE_CONNECTION(self);
686 /* we are only allowed to do this once */
687 if (base->status != TP_CONNECTION_STATUS_CONNECTED)
688 tp_base_connection_change_status(base,
689 TP_CONNECTION_STATUS_CONNECTED,
690 TP_CONNECTION_STATUS_REASON_REQUESTED);
693 void sipe_backend_connection_error(struct sipe_core_public *sipe_public,
694 sipe_connection_error error,
695 const gchar *msg)
697 SipeConnection *self = SIPE_PUBLIC_TO_CONNECTION;
698 TpBaseConnection *base = TP_BASE_CONNECTION(self);
699 GHashTable *details = tp_asv_new("server-message", G_TYPE_STRING, msg,
700 NULL);
701 TpConnectionStatusReason reason;
702 const gchar *name;
704 self->is_disconnecting = TRUE;
706 switch (error) {
707 case SIPE_CONNECTION_ERROR_NETWORK:
708 reason = TP_CONNECTION_STATUS_REASON_NETWORK_ERROR;
709 if (base->status == TP_CONNECTION_STATUS_CONNECTING)
710 name = TP_ERROR_STR_CONNECTION_FAILED;
711 else
712 name = TP_ERROR_STR_CONNECTION_LOST;
713 break;
715 case SIPE_CONNECTION_ERROR_INVALID_USERNAME:
716 case SIPE_CONNECTION_ERROR_INVALID_SETTINGS:
717 case SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED:
718 case SIPE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE:
719 /* copied from haze code. I agree there should be better ones */
720 reason = TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED;
721 name = TP_ERROR_STR_AUTHENTICATION_FAILED;
722 break;
724 default:
725 reason = TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED;
726 name = TP_ERROR_STR_DISCONNECTED;
727 break;
730 SIPE_DEBUG_ERROR("sipe_backend_connection_error: %s (%s)", name, msg);
731 tp_base_connection_disconnect_with_dbus_error(base,
732 name,
733 details,
734 reason);
735 g_hash_table_unref(details);
738 gboolean sipe_backend_connection_is_disconnecting(struct sipe_core_public *sipe_public)
740 SipeConnection *self = SIPE_PUBLIC_TO_CONNECTION;
742 /* disconnect was requested or transport was already disconnected */
743 return(self->is_disconnecting ||
744 self->private.transport == NULL);
747 gboolean sipe_backend_connection_is_valid(struct sipe_core_public *sipe_public)
749 return(!sipe_backend_connection_is_disconnecting(sipe_public));
752 const gchar *sipe_backend_setting(struct sipe_core_public *sipe_public,
753 sipe_setting type)
755 SipeConnection *self = SIPE_PUBLIC_TO_CONNECTION;
756 const gchar *value;
758 switch (type) {
759 case SIPE_SETTING_USER_AGENT:
760 value = self->user_agent;
761 break;
762 default:
763 /* @TODO: update when settings are implemented */
764 value = NULL;
765 break;
768 return(value);
773 Local Variables:
774 mode: c
775 c-file-style: "bsd"
776 indent-tabs-mode: t
777 tab-width: 8
778 End: