2 * @file telepathy-connection.c
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
25 #include <glib-object.h>
26 #include <telepathy-glib/base-connection.h>
27 #include <telepathy-glib/base-protocol.h>
28 #include <telepathy-glib/handle-repo-dynamic.h>
29 #include <telepathy-glib/simple-password-manager.h>
30 #include <telepathy-glib/telepathy-glib.h>
32 #include "sipe-backend.h"
33 #include "sipe-common.h"
34 #include "sipe-core.h"
36 #include "telepathy-private.h"
40 * Connection class - data structures
42 typedef struct _SipeConnectionClass
{
43 TpBaseConnectionClass parent_class
;
44 } SipeConnectionClass
;
46 typedef struct _SipeConnection
{
47 TpBaseConnection parent
;
49 TpSimplePasswordManager
*password_manager
;
51 struct sipe_backend_private
private;
61 * Connection class - type macros
63 static GType
sipe_connection_get_type(void) G_GNUC_CONST
;
64 #define SIPE_TYPE_CONNECTION \
65 (sipe_connection_get_type())
66 #define SIPE_CONNECTION(obj) \
67 (G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_CONNECTION, \
72 * Connection class - type definition
74 G_DEFINE_TYPE(SipeConnection
,
76 TP_TYPE_BASE_CONNECTION
)
79 * Connection class - instance methods
81 static gchar
*normalize_contact(SIPE_UNUSED_PARAMETER TpHandleRepoIface
*repo
,
83 SIPE_UNUSED_PARAMETER gpointer context
,
86 return(sipe_telepathy_protocol_normalize_contact(NULL
, id
, error
));
89 static void create_handle_repos(SIPE_UNUSED_PARAMETER TpBaseConnection
*conn
,
90 TpHandleRepoIface
*repos
[NUM_TP_HANDLE_TYPES
])
92 repos
[TP_HANDLE_TYPE_CONTACT
] = tp_dynamic_handle_repo_new(TP_HANDLE_TYPE_CONTACT
,
97 static gboolean
connect_to_core(SipeConnection
*self
,
100 gchar
*login_domain
= NULL
;
101 gchar
*login_account
= NULL
;
102 struct sipe_core_public
*sipe_public
;
105 /* login name specified? */
106 if (self
->login
&& strlen(self
->login
)) {
107 /* Allowed domain-account separators are / or \ */
108 gchar
**domain_user
= g_strsplit_set(self
->login
, "/\\", 2);
109 gboolean has_domain
= domain_user
[1] != NULL
;
110 SIPE_DEBUG_INFO("connect_to_core: login '%s'", self
->login
);
111 login_domain
= has_domain
? g_strdup(domain_user
[0]) : NULL
;
112 login_account
= g_strdup(domain_user
[has_domain
? 1 : 0]);
113 SIPE_DEBUG_INFO("connect_to_core: auth domain '%s' user '%s'",
114 login_domain
? login_domain
: "",
116 g_strfreev(domain_user
);
119 sipe_public
= sipe_core_allocate(self
->account
,
120 login_domain
, login_account
,
122 NULL
, /* @TODO: email */
123 NULL
, /* @TODO: email_url */
125 g_free(login_domain
);
126 g_free(login_account
);
128 SIPE_DEBUG_INFO("connect_to_core: created %p", sipe_public
);
131 struct sipe_backend_private
*telepathy_private
= &self
->private;
133 /* initialize backend private data */
134 sipe_public
->backend_private
= telepathy_private
;
135 telepathy_private
->public = sipe_public
;
136 telepathy_private
->connection
= self
;
137 telepathy_private
->transport
= NULL
;
138 telepathy_private
->ipaddress
= NULL
;
140 /* map option list to flags - default is NTLM */
141 SIPE_CORE_FLAG_UNSET(KRB5
);
142 SIPE_CORE_FLAG_UNSET(TLS_DSK
);
143 SIPE_CORE_FLAG_UNSET(SSO
);
144 /* @TODO: add parameters for these */
146 sipe_core_transport_sip_connect(sipe_public
,
153 g_set_error_literal(error
, TP_ERROR
, TP_ERROR_INVALID_ARGUMENT
,
159 static void password_manager_cb(GObject
*source
,
160 GAsyncResult
*result
,
163 SipeConnection
*self
= data
;
164 TpBaseConnection
*base
= TP_BASE_CONNECTION(self
);
165 GError
*error
= NULL
;
166 const GString
*password
= tp_simple_password_manager_prompt_finish(
167 TP_SIMPLE_PASSWORD_MANAGER(source
),
172 SIPE_DEBUG_ERROR("password_manager_cb: failed: %s",
175 if (base
->status
!= TP_CONNECTION_STATUS_DISCONNECTED
) {
176 tp_base_connection_disconnect_with_dbus_error(base
,
177 tp_error_get_dbus_name(error
->code
),
179 TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED
);
184 g_free(self
->password
);
185 self
->password
= g_strdup(password
->str
);
187 if (!connect_to_core(self
, &error
)) {
188 if (base
->status
!= TP_CONNECTION_STATUS_DISCONNECTED
) {
189 tp_base_connection_disconnect_with_dbus_error(base
,
190 tp_error_get_dbus_name(error
->code
),
192 TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED
);
199 static gboolean
start_connecting(TpBaseConnection
*base
,
202 SipeConnection
*self
= SIPE_CONNECTION(base
);
205 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::start_connecting");
207 tp_base_connection_change_status(base
, TP_CONNECTION_STATUS_CONNECTING
,
208 TP_CONNECTION_STATUS_REASON_REQUESTED
);
210 /* we need a password */
212 rc
= connect_to_core(self
, error
);
215 /* this doesn't work. Nobody has a clue why */
216 SIPE_DEBUG_INFO("SipeConnection::start_connecting: requesting password from user: %p",
217 self
->password_manager
);
218 tp_simple_password_manager_prompt_async(self
->password_manager
,
223 gchar
*password_file
= g_strdup_printf("%s/.sipe-password",
225 SIPE_DEBUG_INFO("SipeConnection::start_connecting - password file %s",
228 if (g_file_get_contents(password_file
,
231 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::start_connecting - got password");
232 g_strchomp(self
->password
);
233 rc
= connect_to_core(self
, error
);
235 SIPE_DEBUG_ERROR("SipeConnection::start_connecting: %s",
238 g_free(password_file
);
240 /* to make compiler happy */
241 (void)password_manager_cb
;
248 static void shut_down(TpBaseConnection
*base
)
250 SipeConnection
*self
= SIPE_CONNECTION(base
);
251 struct sipe_backend_private
*telepathy_private
= &self
->private;
252 struct sipe_core_public
*sipe_public
= telepathy_private
->public;
254 SIPE_DEBUG_INFO("SipeConnection::shut_down: closing %p", sipe_public
);
257 sipe_core_deallocate(sipe_public
);
258 telepathy_private
->public = NULL
;
259 telepathy_private
->transport
= NULL
;
261 g_free(telepathy_private
->ipaddress
);
262 telepathy_private
->ipaddress
= NULL
;
264 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::shut_down: core deallocated");
267 static GPtrArray
*create_channel_managers(TpBaseConnection
*base
)
269 SipeConnection
*self
= SIPE_CONNECTION(base
);
270 GPtrArray
*channel_managers
= g_ptr_array_new();
272 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::create_channel_managers");
274 self
->password_manager
= tp_simple_password_manager_new(base
);
275 g_ptr_array_add(channel_managers
, self
->password_manager
);
276 SIPE_DEBUG_INFO("SipeConnection::create_channel_managers: password %p",
277 self
->password_manager
);
279 return(channel_managers
);
282 static void sipe_connection_finalize(GObject
*object
)
284 SipeConnection
*self
= SIPE_CONNECTION(object
);
286 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::finalize");
289 g_free(self
->server
);
290 g_free(self
->password
);
292 g_free(self
->account
);
294 G_OBJECT_CLASS(sipe_connection_parent_class
)->finalize(object
);
298 * Connection class - type implementation
300 static void sipe_connection_class_init(SipeConnectionClass
*klass
)
302 GObjectClass
*object_class
= G_OBJECT_CLASS(klass
);
303 TpBaseConnectionClass
*base_class
= TP_BASE_CONNECTION_CLASS(klass
);
305 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::class_init");
307 object_class
->finalize
= sipe_connection_finalize
;
309 base_class
->create_handle_repos
= create_handle_repos
;
310 base_class
->start_connecting
= start_connecting
;
311 base_class
->shut_down
= shut_down
;
312 base_class
->create_channel_managers
= create_channel_managers
;
315 static void sipe_connection_init(SIPE_UNUSED_PARAMETER SipeConnection
*self
)
317 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::init");
320 /* create new connection object */
321 TpBaseConnection
*sipe_telepathy_connection_new(TpBaseProtocol
*protocol
,
323 SIPE_UNUSED_PARAMETER GError
**error
)
325 const gchar
*password
= tp_asv_get_string(params
, "password");
326 const gchar
*server
= tp_asv_get_string(params
, "server");
327 const gchar
*transport
= tp_asv_get_string(params
, "transport");
328 SipeConnection
*conn
= g_object_new(SIPE_TYPE_CONNECTION
,
329 "protocol", tp_base_protocol_get_name(protocol
),
334 SIPE_DEBUG_INFO_NOFORMAT("sipe_telepathy_connection_new");
336 /* account & login are required fields */
337 conn
->account
= g_strdup(tp_asv_get_string(params
, "account"));
338 conn
->login
= g_strdup(tp_asv_get_string(params
, "login"));
341 if (password
&& strlen(password
))
342 conn
->password
= g_strdup(password
);
344 conn
->password
= NULL
;
347 if (server
&& strlen(server
))
348 conn
->server
= g_strdup(server
);
352 /* server port: core expects a string */
353 port
= tp_asv_get_uint32(params
, "port", &valid
);
355 conn
->port
= g_strdup_printf("%d", port
);
360 if (sipe_strequal(transport
, "auto")) {
361 conn
->transport
= conn
->server
?
362 SIPE_TRANSPORT_TLS
: SIPE_TRANSPORT_AUTO
;
363 } else if (sipe_strequal(transport
, "tls")) {
364 conn
->transport
= SIPE_TRANSPORT_TLS
;
366 conn
->transport
= SIPE_TRANSPORT_TCP
;
369 return(TP_BASE_CONNECTION(conn
));
374 * Backend adaptor functions
376 gboolean
sipe_backend_connection_is_valid(struct sipe_core_public
*sipe_public
) {
377 return(sipe_public
->backend_private
->transport
!= NULL
);