2 * @file telepathy-connection.c
6 * Copyright (C) 2012-2017 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
30 #include <glib-object.h>
31 #include <glib/gstdio.h>
32 #include <telepathy-glib/base-connection.h>
33 #include <telepathy-glib/base-protocol.h>
34 #include <telepathy-glib/contacts-mixin.h>
35 #include <telepathy-glib/handle-repo-dynamic.h>
36 #include <telepathy-glib/presence-mixin.h>
37 #include <telepathy-glib/simple-password-manager.h>
38 #include <telepathy-glib/telepathy-glib.h>
40 #include "sipe-backend.h"
41 #include "sipe-common.h"
42 #include "sipe-core.h"
44 #include "telepathy-private.h"
48 * Connection class - data structures
50 typedef struct _SipeConnectionClass
{
51 TpBaseConnectionClass parent_class
;
52 TpDBusPropertiesMixinClass properties_mixin
;
53 TpContactsMixinClass contacts_mixin
;
54 TpPresenceMixinClass presence_mixin
;
55 } SipeConnectionClass
;
57 typedef struct _SipeConnection
{
58 TpBaseConnection parent
;
59 TpContactsMixinClass contacts_mixin
;
60 TpPresenceMixin presence_mixin
;
62 /* channel managers */
63 TpSimplePasswordManager
*password_manager
;
64 struct _SipeContactList
*contact_list
;
65 struct _SipeTLSManager
*tls_manager
;
67 struct sipe_backend_private
private;
74 guint authentication_type
;
76 gchar
*authentication
;
78 gboolean dont_publish
;
79 gboolean allow_web_photo
;
80 gboolean is_disconnecting
;
82 GPtrArray
*contact_info_fields
;
85 #define SIPE_PUBLIC_TO_CONNECTION sipe_public->backend_private->connection
88 * Connection class - type macros
90 static GType
sipe_connection_get_type(void) G_GNUC_CONST
;
91 #define SIPE_TYPE_CONNECTION \
92 (sipe_connection_get_type())
93 #define SIPE_CONNECTION(obj) \
94 (G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_CONNECTION, \
99 * Connection class - type definition
101 static void init_aliasing (gpointer
, gpointer
);
102 G_DEFINE_TYPE_WITH_CODE(SipeConnection
,
104 TP_TYPE_BASE_CONNECTION
,
105 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING
,
107 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_AVATARS
,
108 sipe_telepathy_avatars_iface_init
);
109 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACTS
,
110 tp_contacts_mixin_iface_init
);
111 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_GROUPS
,
112 tp_base_contact_list_mixin_groups_iface_init
);
113 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_INFO
,
114 sipe_telepathy_contact_info_iface_init
);
115 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_LIST
,
116 tp_base_contact_list_mixin_list_iface_init
);
117 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_PRESENCE
,
118 tp_presence_mixin_iface_init
);
119 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_SIMPLE_PRESENCE
,
120 tp_presence_mixin_simple_presence_iface_init
);
121 G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_DBUS_PROPERTIES
,
122 tp_dbus_properties_mixin_iface_init
);
127 * Connection class - instance methods
129 static gchar
*normalize_contact(SIPE_UNUSED_PARAMETER TpHandleRepoIface
*repo
,
131 SIPE_UNUSED_PARAMETER gpointer context
,
134 return(sipe_telepathy_protocol_normalize_contact(NULL
, id
, error
));
137 static void create_handle_repos(SIPE_UNUSED_PARAMETER TpBaseConnection
*conn
,
138 TpHandleRepoIface
*repos
[NUM_TP_HANDLE_TYPES
])
140 repos
[TP_HANDLE_TYPE_CONTACT
] = tp_dynamic_handle_repo_new(TP_HANDLE_TYPE_CONTACT
,
145 static gboolean
connect_to_core(SipeConnection
*self
,
148 struct sipe_core_public
*sipe_public
;
151 sipe_public
= sipe_core_allocate(self
->account
,
155 NULL
, /* @TODO: email */
156 NULL
, /* @TODO: email_url */
159 SIPE_DEBUG_INFO("connect_to_core: created %p", sipe_public
);
162 struct sipe_backend_private
*telepathy_private
= &self
->private;
164 /* initialize backend private data */
165 sipe_public
->backend_private
= telepathy_private
;
166 telepathy_private
->public = sipe_public
;
167 telepathy_private
->contact_list
= self
->contact_list
;
168 telepathy_private
->connection
= self
;
169 telepathy_private
->activity
= SIPE_ACTIVITY_UNSET
;
170 telepathy_private
->cache_dir
= g_build_path(G_DIR_SEPARATOR_S
,
171 g_get_user_cache_dir(),
176 telepathy_private
->message
= NULL
;
177 telepathy_private
->tls_manager
= self
->tls_manager
;
178 telepathy_private
->transport
= NULL
;
180 /* make sure cache directory exists */
181 if (!g_file_test(telepathy_private
->cache_dir
,
182 G_FILE_TEST_IS_DIR
) &&
183 (g_mkdir_with_parents(telepathy_private
->cache_dir
,
184 S_IRWXU
| S_IRGRP
| S_IXGRP
| S_IROTH
| S_IXOTH
)
186 SIPE_DEBUG_INFO("connect_to_core: created cache directory %s",
187 telepathy_private
->cache_dir
);
189 SIPE_CORE_FLAG_UNSET(DONT_PUBLISH
);
190 if (self
->dont_publish
)
191 SIPE_CORE_FLAG_SET(DONT_PUBLISH
);
192 SIPE_CORE_FLAG_UNSET(ALLOW_WEB_PHOTO
);
193 if (self
->allow_web_photo
)
194 SIPE_CORE_FLAG_SET(ALLOW_WEB_PHOTO
);
196 sipe_core_transport_sip_connect(sipe_public
,
198 self
->authentication_type
,
204 g_set_error_literal(error
, TP_ERROR
, TP_ERROR_INVALID_ARGUMENT
,
210 static void password_manager_cb(GObject
*source
,
211 GAsyncResult
*result
,
214 SipeConnection
*self
= data
;
215 TpBaseConnection
*base
= TP_BASE_CONNECTION(self
);
216 GError
*error
= NULL
;
217 const GString
*password
= tp_simple_password_manager_prompt_finish(
218 TP_SIMPLE_PASSWORD_MANAGER(source
),
222 if (password
== NULL
) {
223 SIPE_DEBUG_ERROR("password_manager_cb: failed: %s",
224 error
? error
->message
: "UNKNOWN");
226 if (base
->status
!= TP_CONNECTION_STATUS_DISCONNECTED
) {
227 tp_base_connection_disconnect_with_dbus_error(base
,
228 error
? tp_error_get_dbus_name(error
->code
) : "",
230 TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED
);
236 g_free(self
->password
);
237 self
->password
= g_strdup(password
->str
);
239 if (!connect_to_core(self
, &error
)) {
240 if (base
->status
!= TP_CONNECTION_STATUS_DISCONNECTED
) {
241 tp_base_connection_disconnect_with_dbus_error(base
,
242 tp_error_get_dbus_name(error
->code
),
244 TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED
);
251 static gboolean
start_connecting(TpBaseConnection
*base
,
254 SipeConnection
*self
= SIPE_CONNECTION(base
);
256 gchar
*uri
= sipe_telepathy_protocol_normalize_contact(NULL
,
260 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::start_connecting");
262 /* set up mandatory self-handle */
264 base
->self_handle
= tp_handle_ensure(tp_base_connection_get_handles(base
,
265 TP_HANDLE_TYPE_CONTACT
),
270 if (!base
->self_handle
) {
271 SIPE_DEBUG_ERROR("SipeConnection::start_connecting: self handle creation failed: %s",
276 SIPE_DEBUG_ERROR("SipeConnection::start_connecting: %s",
281 tp_base_connection_change_status(base
, TP_CONNECTION_STATUS_CONNECTING
,
282 TP_CONNECTION_STATUS_REASON_REQUESTED
);
284 /* map option list to flags - default is automatic */
285 self
->authentication_type
= SIPE_AUTHENTICATION_TYPE_AUTOMATIC
;
286 if (sipe_strequal(self
->authentication
, "ntlm")) {
287 SIPE_DEBUG_INFO_NOFORMAT("start_connecting: NTLM selected");
288 self
->authentication_type
= SIPE_AUTHENTICATION_TYPE_NTLM
;
290 #ifdef HAVE_GSSAPI_GSSAPI_H
291 if (sipe_strequal(self
->authentication
, "krb5")) {
292 SIPE_DEBUG_INFO_NOFORMAT("start_connecting: KRB5 selected");
293 self
->authentication_type
= SIPE_AUTHENTICATION_TYPE_KERBEROS
;
296 if (sipe_strequal(self
->authentication
, "tls-dsk")) {
297 SIPE_DEBUG_INFO_NOFORMAT("start_connecting: TLS-DSK selected");
298 self
->authentication_type
= SIPE_AUTHENTICATION_TYPE_TLS_DSK
;
301 /* Only ask for a password when required */
302 if (!sipe_core_transport_sip_requires_password(self
->authentication_type
,
304 (self
->password
&& strlen(self
->password
)))
305 rc
= connect_to_core(self
, error
);
307 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::start_connecting: requesting password from user");
308 tp_simple_password_manager_prompt_async(self
->password_manager
,
316 static gboolean
disconnect_from_core(gpointer data
)
318 TpBaseConnection
*base
= data
;
319 SipeConnection
*self
= SIPE_CONNECTION(base
);
320 struct sipe_backend_private
*telepathy_private
= &self
->private;
321 struct sipe_core_public
*sipe_public
= telepathy_private
->public;
323 SIPE_DEBUG_INFO("disconnect_from_core: %p", sipe_public
);
326 sipe_core_deallocate(sipe_public
);
327 telepathy_private
->public = NULL
;
328 telepathy_private
->transport
= NULL
;
330 g_free(telepathy_private
->message
);
331 telepathy_private
->message
= NULL
;
333 g_free(telepathy_private
->cache_dir
);
334 telepathy_private
->cache_dir
= NULL
;
336 SIPE_DEBUG_INFO_NOFORMAT("disconnect_from_core: core deallocated");
338 /* now it is OK to destroy the connection object */
339 tp_base_connection_finish_shutdown(base
);
344 static void shut_down(TpBaseConnection
*base
)
346 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::shut_down");
348 /* this can be called synchronously, defer destruction */
349 g_idle_add(disconnect_from_core
, base
);
352 static GPtrArray
*create_channel_managers(TpBaseConnection
*base
)
354 SipeConnection
*self
= SIPE_CONNECTION(base
);
355 GPtrArray
*channel_managers
= g_ptr_array_new();
357 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::create_channel_managers");
359 self
->contact_list
= sipe_telepathy_contact_list_new(base
);
360 g_ptr_array_add(channel_managers
, self
->contact_list
);
362 self
->password_manager
= tp_simple_password_manager_new(base
);
363 g_ptr_array_add(channel_managers
, self
->password_manager
);
365 g_ptr_array_add(channel_managers
, sipe_telepathy_search_new(base
));
367 self
->tls_manager
= sipe_telepathy_tls_new(base
);
368 g_ptr_array_add(channel_managers
, self
->tls_manager
);
370 return(channel_managers
);
373 static void aliasing_fill_contact_attributes(GObject
*object
,
374 const GArray
*contacts
,
375 GHashTable
*attributes
)
377 SipeConnection
*self
= SIPE_CONNECTION(object
);
380 for (i
= 0; i
< contacts
->len
; i
++) {
381 TpHandle contact
= g_array_index(contacts
, guint
, i
);
383 tp_contacts_mixin_set_contact_attribute(attributes
,
385 TP_TOKEN_CONNECTION_INTERFACE_ALIASING_ALIAS
,
386 tp_g_value_slice_new_string(
387 sipe_telepathy_buddy_get_alias(self
->contact_list
,
392 static void avatars_fill_contact_attributes(GObject
*object
,
393 const GArray
*contacts
,
394 GHashTable
*attributes
)
396 SipeConnection
*self
= SIPE_CONNECTION(object
);
399 for (i
= 0; i
< contacts
->len
; i
++) {
400 TpHandle contact
= g_array_index(contacts
, guint
, i
);
401 const gchar
*hash
= sipe_telepathy_buddy_get_hash(self
->contact_list
,
404 if (!hash
) hash
= "";
405 tp_contacts_mixin_set_contact_attribute(attributes
,
407 TP_IFACE_CONNECTION_INTERFACE_AVATARS
"/token",
408 tp_g_value_slice_new_string(hash
));
412 static void contact_info_properties_getter(GObject
*object
,
413 SIPE_UNUSED_PARAMETER GQuark interface
,
416 gpointer getter_data
)
418 GQuark fields
= g_quark_from_static_string("SupportedFields");
421 g_value_set_boxed(value
,
422 SIPE_CONNECTION(object
)->contact_info_fields
);
424 g_value_set_uint(value
,
425 GPOINTER_TO_UINT(getter_data
));
428 static void sipe_connection_constructed(GObject
*object
)
430 SipeConnection
*self
= SIPE_CONNECTION(object
);
431 TpBaseConnection
*base
= TP_BASE_CONNECTION(object
);
432 void (*chain_up
)(GObject
*) = G_OBJECT_CLASS(sipe_connection_parent_class
)->constructed
;
437 tp_contacts_mixin_init(object
,
438 G_STRUCT_OFFSET(SipeConnection
, contacts_mixin
));
439 tp_base_connection_register_with_contacts_mixin(base
);
441 tp_base_contact_list_mixin_register_with_contacts_mixin(base
);
443 tp_contacts_mixin_add_contact_attributes_iface(object
,
444 TP_IFACE_CONNECTION_INTERFACE_ALIASING
,
445 aliasing_fill_contact_attributes
);
446 tp_contacts_mixin_add_contact_attributes_iface(object
,
447 TP_IFACE_CONNECTION_INTERFACE_AVATARS
,
448 avatars_fill_contact_attributes
);
450 tp_presence_mixin_init(object
,
451 G_STRUCT_OFFSET(SipeConnection
,
453 tp_presence_mixin_simple_presence_register_with_contacts_mixin(object
);
455 self
->contact_info_fields
= sipe_telepathy_contact_info_fields();
458 static void sipe_connection_finalize(GObject
*object
)
460 SipeConnection
*self
= SIPE_CONNECTION(object
);
462 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::finalize");
464 tp_contacts_mixin_finalize(object
);
465 tp_presence_mixin_finalize(object
);
466 g_boxed_free(TP_ARRAY_TYPE_FIELD_SPECS
, self
->contact_info_fields
);
468 g_free(self
->authentication
);
469 g_free(self
->user_agent
);
471 g_free(self
->server
);
472 g_free(self
->password
);
474 g_free(self
->account
);
476 G_OBJECT_CLASS(sipe_connection_parent_class
)->finalize(object
);
480 * Connection class - type implementation
482 static const gchar
*interfaces_always_present
[] = {
484 TP_IFACE_CONNECTION_INTERFACE_ALIASING
,
485 TP_IFACE_CONNECTION_INTERFACE_AVATARS
,
486 TP_IFACE_CONNECTION_INTERFACE_CONTACT_GROUPS
,
487 TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO
,
488 TP_IFACE_CONNECTION_INTERFACE_CONTACT_LIST
,
489 TP_IFACE_CONNECTION_INTERFACE_CONTACTS
,
490 TP_IFACE_CONNECTION_INTERFACE_PRESENCE
,
491 TP_IFACE_CONNECTION_INTERFACE_REQUESTS
,
492 TP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE
,
496 static void sipe_connection_class_init(SipeConnectionClass
*klass
)
498 GObjectClass
*object_class
= G_OBJECT_CLASS(klass
);
499 TpBaseConnectionClass
*base_class
= TP_BASE_CONNECTION_CLASS(klass
);
500 static TpDBusPropertiesMixinIfaceImpl prop_interfaces
[] = {
503 .name
= TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO
,
504 .getter
= contact_info_properties_getter
,
513 /* initalize non-constant fields */
514 prop_interfaces
[0].props
= sipe_telepathy_contact_info_props();
516 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::class_init");
518 object_class
->constructed
= sipe_connection_constructed
;
519 object_class
->finalize
= sipe_connection_finalize
;
521 base_class
->create_handle_repos
= create_handle_repos
;
522 base_class
->start_connecting
= start_connecting
;
523 base_class
->shut_down
= shut_down
;
524 base_class
->create_channel_managers
= create_channel_managers
;
526 base_class
->interfaces_always_present
= interfaces_always_present
;
528 klass
->properties_mixin
.interfaces
= prop_interfaces
;
529 tp_dbus_properties_mixin_class_init(object_class
,
530 G_STRUCT_OFFSET(SipeConnectionClass
,
532 tp_contacts_mixin_class_init(object_class
,
533 G_STRUCT_OFFSET(SipeConnectionClass
,
535 sipe_telepathy_status_init(object_class
,
536 G_STRUCT_OFFSET(SipeConnectionClass
,
538 tp_presence_mixin_simple_presence_init_dbus_properties(object_class
);
539 tp_base_contact_list_mixin_class_init(base_class
);
542 static void sipe_connection_init(SIPE_UNUSED_PARAMETER SipeConnection
*self
)
544 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::init");
548 * Connection class - interface implementation
552 static void get_alias_flags(TpSvcConnectionInterfaceAliasing
*aliasing
,
553 DBusGMethodInvocation
*context
)
555 TpBaseConnection
*base
= TP_BASE_CONNECTION(aliasing
);
557 TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED(base
, context
);
558 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::get_alias_flags called");
560 tp_svc_connection_interface_aliasing_return_from_get_alias_flags(context
,
561 TP_CONNECTION_ALIAS_FLAG_USER_SET
);
564 static void get_aliases(TpSvcConnectionInterfaceAliasing
*aliasing
,
565 const GArray
*contacts
,
566 DBusGMethodInvocation
*context
)
568 SipeConnection
*self
= SIPE_CONNECTION(aliasing
);
569 TpBaseConnection
*base
= TP_BASE_CONNECTION(aliasing
);
570 TpHandleRepoIface
*contact_repo
= tp_base_connection_get_handles(base
,
571 TP_HANDLE_TYPE_CONTACT
);
572 GError
*error
= NULL
;
576 TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED(base
, context
);
577 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::get_aliases called");
579 if (!tp_handles_are_valid(contact_repo
, contacts
, FALSE
, &error
)) {
580 dbus_g_method_return_error(context
, error
);
585 result
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
587 for (i
= 0; i
< contacts
->len
; i
++) {
588 TpHandle contact
= g_array_index(contacts
, TpHandle
, i
);
589 const gchar
*alias
= sipe_telepathy_buddy_get_alias(self
->contact_list
,
591 g_hash_table_insert(result
,
592 GUINT_TO_POINTER(contact
),
596 tp_svc_connection_interface_aliasing_return_from_get_aliases(context
,
598 g_hash_table_unref(result
);
601 static void request_aliases(TpSvcConnectionInterfaceAliasing
*aliasing
,
602 const GArray
*contacts
,
603 DBusGMethodInvocation
*context
)
605 SipeConnection
*self
= SIPE_CONNECTION(aliasing
);
606 TpBaseConnection
*base
= TP_BASE_CONNECTION(aliasing
);
607 TpHandleRepoIface
*contact_repo
= tp_base_connection_get_handles(base
,
608 TP_HANDLE_TYPE_CONTACT
);
609 GError
*error
= NULL
;
614 TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED(base
, context
);
615 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::request_aliases called");
617 if (!tp_handles_are_valid(contact_repo
, contacts
, FALSE
, &error
)) {
618 dbus_g_method_return_error(context
, error
);
623 result
= g_ptr_array_sized_new(contacts
->len
+ 1);
625 for (i
= 0; i
< contacts
->len
; i
++) {
626 TpHandle contact
= g_array_index(contacts
, TpHandle
, i
);
627 const gchar
*alias
= sipe_telepathy_buddy_get_alias(self
->contact_list
,
629 g_ptr_array_add(result
, (gchar
*) alias
);
632 g_ptr_array_add(result
, NULL
);
633 strings
= (gchar
**) g_ptr_array_free(result
, FALSE
);
635 tp_svc_connection_interface_aliasing_return_from_request_aliases(context
,
636 (const gchar
**) strings
);
640 static void set_aliases(TpSvcConnectionInterfaceAliasing
*aliasing
,
642 DBusGMethodInvocation
*context
)
644 SipeConnection
*self
= SIPE_CONNECTION(aliasing
);
645 TpBaseConnection
*base
= TP_BASE_CONNECTION(aliasing
);
646 TpHandleRepoIface
*contact_repo
= tp_base_connection_get_handles(base
,
647 TP_HANDLE_TYPE_CONTACT
);
651 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::set_aliases called");
653 g_hash_table_iter_init(&iter
, aliases
);
655 while (g_hash_table_iter_next(&iter
, &key
, NULL
)) {
656 GError
*error
= NULL
;
658 if (!tp_handle_is_valid(contact_repo
,
659 GPOINTER_TO_UINT(key
),
661 dbus_g_method_return_error(context
, error
);
667 g_hash_table_iter_init(&iter
, aliases
);
669 while (g_hash_table_iter_next(&iter
, &key
, &value
)) {
670 sipe_telepathy_buddy_set_alias(self
->contact_list
,
671 GPOINTER_TO_UINT(key
),
675 tp_svc_connection_interface_aliasing_return_from_set_aliases(context
);
678 static void init_aliasing(gpointer iface
,
679 SIPE_UNUSED_PARAMETER gpointer iface_data
)
681 TpSvcConnectionInterfaceAliasingClass
*klass
= iface
;
683 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::init_aliasing called");
685 tp_svc_connection_interface_aliasing_implement_get_alias_flags(klass
, get_alias_flags
);
686 tp_svc_connection_interface_aliasing_implement_request_aliases(klass
, request_aliases
);
687 tp_svc_connection_interface_aliasing_implement_get_aliases(klass
, get_aliases
);
688 tp_svc_connection_interface_aliasing_implement_set_aliases(klass
, set_aliases
);
691 /* create new connection object */
692 TpBaseConnection
*sipe_telepathy_connection_new(TpBaseProtocol
*protocol
,
694 SIPE_UNUSED_PARAMETER GError
**error
)
696 SipeConnection
*conn
= g_object_new(SIPE_TYPE_CONNECTION
,
697 "protocol", tp_base_protocol_get_name(protocol
),
701 gboolean boolean_value
;
704 SIPE_DEBUG_INFO_NOFORMAT("sipe_telepathy_connection_new");
706 /* initialize private fields */
707 conn
->is_disconnecting
= FALSE
;
709 /* account is required field */
710 conn
->account
= g_strdup(tp_asv_get_string(params
, "account"));
712 /* if login is not specified, account value will be used in connect_to_core */
713 value
= tp_asv_get_string(params
, "login");
714 if (value
&& strlen(value
))
715 conn
->login
= g_strdup(value
);
720 value
= tp_asv_get_string(params
, "password");
721 if (value
&& strlen(value
))
722 conn
->password
= g_strdup(value
);
724 conn
->password
= NULL
;
727 value
= tp_asv_get_string(params
, "server");
728 if (value
&& strlen(value
))
729 conn
->server
= g_strdup(value
);
733 /* server port: core expects a string */
734 port
= tp_asv_get_uint32(params
, "port", &valid
);
736 conn
->port
= g_strdup_printf("%d", port
);
741 value
= tp_asv_get_string(params
, "transport");
742 if (sipe_strequal(value
, "auto")) {
743 conn
->transport
= conn
->server
?
744 SIPE_TRANSPORT_TLS
: SIPE_TRANSPORT_AUTO
;
745 } else if (sipe_strequal(value
, "tls")) {
746 conn
->transport
= SIPE_TRANSPORT_TLS
;
748 conn
->transport
= SIPE_TRANSPORT_TCP
;
751 /* User-Agent: override */
752 value
= tp_asv_get_string(params
, "useragent");
753 if (value
&& strlen(value
))
754 conn
->user_agent
= g_strdup(value
);
756 conn
->user_agent
= NULL
;
758 /* authentication type */
759 value
= tp_asv_get_string(params
, "authentication");
760 if (value
&& strlen(value
) && strcmp(value
, "ntlm"))
761 conn
->authentication
= g_strdup(value
);
763 conn
->authentication
= NULL
; /* NTLM is default */
766 boolean_value
= tp_asv_get_boolean(params
, "single-sign-on", &valid
);
768 conn
->sso
= boolean_value
;
772 /* Don't publish my calendar information */
773 boolean_value
= tp_asv_get_boolean(params
, "don't-publish-calendar", &valid
);
775 conn
->dont_publish
= boolean_value
;
777 conn
->dont_publish
= FALSE
;
779 /* Allow insecure download of buddy icons from web */
780 boolean_value
= tp_asv_get_boolean(params
, "allow-web-photo", &valid
);
782 conn
->allow_web_photo
= boolean_value
;
784 conn
->allow_web_photo
= FALSE
;
786 return(TP_BASE_CONNECTION(conn
));
789 void sipe_telepathy_connection_alias_updated(TpBaseConnection
*connection
,
793 GPtrArray
*aliases
= g_ptr_array_sized_new(1);
794 GValueArray
*pair
= g_value_array_new(2);
796 g_value_array_append(pair
, NULL
);
797 g_value_array_append(pair
, NULL
);
798 g_value_init(pair
->values
+ 0, G_TYPE_UINT
);
799 g_value_init(pair
->values
+ 1, G_TYPE_STRING
);
800 g_value_set_uint(pair
->values
+ 0, contact
);
801 g_value_set_string(pair
->values
+ 1, alias
);
802 g_ptr_array_add(aliases
, pair
);
804 tp_svc_connection_interface_aliasing_emit_aliases_changed(SIPE_CONNECTION(connection
),
807 g_ptr_array_unref(aliases
);
808 g_value_array_free(pair
);
811 struct sipe_backend_private
*sipe_telepathy_connection_private(GObject
*object
)
813 SipeConnection
*self
= SIPE_CONNECTION(object
);
814 /* connected to core already? */
815 if (self
->private.public)
816 return(&self
->private);
822 * Backend adaptor functions
824 void sipe_backend_connection_completed(struct sipe_core_public
*sipe_public
)
826 SipeConnection
*self
= SIPE_PUBLIC_TO_CONNECTION
;
827 TpBaseConnection
*base
= TP_BASE_CONNECTION(self
);
829 /* we are only allowed to do this once */
830 if (base
->status
!= TP_CONNECTION_STATUS_CONNECTED
)
831 tp_base_connection_change_status(base
,
832 TP_CONNECTION_STATUS_CONNECTED
,
833 TP_CONNECTION_STATUS_REASON_REQUESTED
);
836 void sipe_backend_connection_error(struct sipe_core_public
*sipe_public
,
837 sipe_connection_error error
,
840 SipeConnection
*self
= SIPE_PUBLIC_TO_CONNECTION
;
841 TpBaseConnection
*base
= TP_BASE_CONNECTION(self
);
842 GHashTable
*details
= tp_asv_new("server-message", G_TYPE_STRING
, msg
,
844 TpConnectionStatusReason reason
;
847 self
->is_disconnecting
= TRUE
;
850 case SIPE_CONNECTION_ERROR_NETWORK
:
851 reason
= TP_CONNECTION_STATUS_REASON_NETWORK_ERROR
;
852 if (base
->status
== TP_CONNECTION_STATUS_CONNECTING
)
853 name
= TP_ERROR_STR_CONNECTION_FAILED
;
855 name
= TP_ERROR_STR_CONNECTION_LOST
;
858 case SIPE_CONNECTION_ERROR_INVALID_USERNAME
:
859 case SIPE_CONNECTION_ERROR_INVALID_SETTINGS
:
860 case SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED
:
861 case SIPE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE
:
862 /* copied from haze code. I agree there should be better ones */
863 reason
= TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED
;
864 name
= TP_ERROR_STR_AUTHENTICATION_FAILED
;
868 reason
= TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED
;
869 name
= TP_ERROR_STR_DISCONNECTED
;
873 SIPE_DEBUG_ERROR("sipe_backend_connection_error: %s (%s)", name
, msg
);
874 tp_base_connection_disconnect_with_dbus_error(base
,
878 g_hash_table_unref(details
);
881 gboolean
sipe_backend_connection_is_disconnecting(struct sipe_core_public
*sipe_public
)
883 SipeConnection
*self
= SIPE_PUBLIC_TO_CONNECTION
;
885 /* disconnect was requested or transport was already disconnected */
886 return(self
->is_disconnecting
||
887 self
->private.transport
== NULL
);
890 gboolean
sipe_backend_connection_is_valid(struct sipe_core_public
*sipe_public
)
892 return(!sipe_backend_connection_is_disconnecting(sipe_public
));
895 const gchar
*sipe_backend_setting(struct sipe_core_public
*sipe_public
,
898 SipeConnection
*self
= SIPE_PUBLIC_TO_CONNECTION
;
902 case SIPE_SETTING_USER_AGENT
:
903 value
= self
->user_agent
;
906 /* @TODO: update when settings are implemented */