comparison libpurple/disco.c @ 26974:c2cd559e034f

propagate from branch 'im.pidgin.pidgin' (head 97fbf033d9afea69a6eabaac94698b3c051584cf) to branch 'im.pidgin.cpw.darkrain42.xmpp.disco' (head d1274de628e3e7c76742ebf0941b7d104e19dceb)
author Paul Aurich <paul@darkrain42.org>
date Sat, 23 May 2009 22:46:28 +0000
parents ba99ee519926
children
comparison
equal deleted inserted replaced
26942:7957a5ed53bb 26974:c2cd559e034f
1 /**
2 * @file disco.c Service Discovery API
3 * @ingroup core
4 */
5
6 /* purple
7 *
8 * Purple is the legal property of its developers, whose names are too numerous
9 * to list here. Please refer to the COPYRIGHT file distributed with this
10 * source distribution.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
25 */
26
27 #include "internal.h"
28 #include "debug.h"
29
30 #include "disco.h"
31
32 /**************************************************************************/
33 /* Main structures, members and constants */
34 /**************************************************************************/
35
36 /**
37 * Represents a list of services for a given connection on a given protocol.
38 */
39 struct _PurpleDiscoList {
40 PurpleAccount *account; /**< The account this list belongs to. */
41 GList *services; /**< The list of services. */
42
43 gboolean in_progress;
44
45 gpointer ui_data; /**< UI private data. */
46 gpointer proto_data; /**< Prpl private data. */
47 guint ref; /**< The reference count. */
48
49 struct {
50 PurpleDiscoCancelFunc cancel_cb;
51 PurpleDiscoCloseFunc close_cb; /**< Callback to free the prpl data */
52 PurpleDiscoServiceCloseFunc service_close_cb;
53 PurpleDiscoServiceExpandFunc expand_cb; /**< Expand a service (iteratively
54 look for things that are
55 "sub-elements" in the tree */
56 PurpleDiscoRegisterFunc register_cb;
57 } ops;
58 };
59
60 /**
61 * Represents a list of services for a given connection on a given protocol.
62 */
63 struct _PurpleDiscoService {
64 PurpleDiscoList *list;
65 gchar *name; /**< The name of the service. */
66 gchar *description; /**< The name of the service. */
67
68 gpointer proto_data;
69
70 gchar *gateway_type; /**< The type of the gateway service. */
71 PurpleDiscoServiceType type; /**< The type of service. */
72 PurpleDiscoServiceFlags flags;
73 };
74
75 static PurpleDiscoUiOps *ops = NULL;
76
77 PurpleDiscoList *purple_disco_list_new(PurpleAccount *account)
78 {
79 PurpleDiscoList *list;
80
81 g_return_val_if_fail(account != NULL, NULL);
82
83 list = g_new0(PurpleDiscoList, 1);
84 list->account = account;
85 list->ref = 1;
86
87 if (ops && ops->create)
88 ops->create(list);
89
90 return list;
91 }
92
93 PurpleDiscoList *purple_disco_list_ref(PurpleDiscoList *list)
94 {
95 g_return_val_if_fail(list != NULL, NULL);
96
97 list->ref++;
98 purple_debug_misc("disco", "reffing list, ref count now %d\n", list->ref);
99
100 return list;
101 }
102
103 static void purple_disco_list_service_destroy(PurpleDiscoList *list, PurpleDiscoService *r)
104 {
105 if (list->ops.service_close_cb)
106 list->ops.service_close_cb(r);
107
108 g_free(r->name);
109 g_free(r->description);
110 g_free(r->gateway_type);
111 g_free(r);
112 }
113
114 static void purple_disco_list_destroy(PurpleDiscoList *list)
115 {
116 GList *l;
117
118 purple_debug_misc("disco", "destroying list %p\n", list);
119
120 if (ops && ops->destroy)
121 ops->destroy(list);
122
123 if (list->ops.close_cb)
124 list->ops.close_cb(list);
125
126 for (l = list->services; l; l = l->next) {
127 PurpleDiscoService *s = l->data;
128 purple_disco_list_service_destroy(list, s);
129 }
130 g_list_free(list->services);
131
132 g_free(list);
133 }
134
135 void purple_disco_list_unref(PurpleDiscoList *list)
136 {
137 g_return_if_fail(list != NULL);
138 g_return_if_fail(list->ref > 0);
139
140 list->ref--;
141
142 purple_debug_misc("disco", "unreffing list, ref count now %d\n", list->ref);
143 if (list->ref == 0)
144 purple_disco_list_destroy(list);
145 }
146
147 void purple_disco_list_service_add(PurpleDiscoList *list,
148 PurpleDiscoService *service,
149 PurpleDiscoService *parent)
150 {
151 g_return_if_fail(list != NULL);
152 g_return_if_fail(service != NULL);
153
154 list->services = g_list_append(list->services, service);
155 service->list = list;
156
157 if (ops && ops->add_service)
158 ops->add_service(list, service, parent);
159 }
160
161 PurpleDiscoService *purple_disco_list_service_new(PurpleDiscoServiceType type,
162 const gchar *name, const gchar *description,
163 PurpleDiscoServiceFlags flags, gpointer proto_data)
164 {
165 PurpleDiscoService *s;
166
167 g_return_val_if_fail(name != NULL, NULL);
168 g_return_val_if_fail(type != PURPLE_DISCO_SERVICE_TYPE_UNSET, NULL);
169
170 s = g_new0(PurpleDiscoService, 1);
171 s->name = g_strdup(name);
172 s->type = type;
173 s->description = g_strdup(description);
174 s->flags = flags;
175 s->proto_data = proto_data;
176
177 return s;
178 }
179
180 PurpleDiscoList *purple_disco_get_list(PurpleConnection *pc)
181 {
182 PurplePlugin *prpl = NULL;
183 PurplePluginProtocolInfo *prpl_info = NULL;
184
185 g_return_val_if_fail(pc != NULL, NULL);
186
187 prpl = purple_connection_get_prpl(pc);
188 if (prpl != NULL)
189 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
190
191 if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, disco_get_list))
192 return prpl_info->disco_get_list(pc);
193
194 return NULL;
195 }
196
197 void purple_disco_cancel_get_list(PurpleDiscoList *list)
198 {
199 PurpleConnection *pc;
200
201 g_return_if_fail(list != NULL);
202
203 pc = purple_account_get_connection(list->account);
204
205 g_return_if_fail(pc != NULL);
206
207 if (list->ops.cancel_cb)
208 list->ops.cancel_cb(list);
209
210 purple_disco_list_set_in_progress(list, FALSE);
211 }
212
213 void purple_disco_service_expand(PurpleDiscoService *service)
214 {
215 PurpleDiscoList *list;
216 PurpleConnection *pc;
217
218 g_return_if_fail(service != NULL);
219 g_return_if_fail((service->flags & PURPLE_DISCO_BROWSE));
220
221 list = service->list;
222 pc = purple_account_get_connection(list->account);
223
224 g_return_if_fail(pc != NULL);
225
226 purple_disco_list_set_in_progress(list, TRUE);
227
228 if (list->ops.expand_cb)
229 list->ops.expand_cb(list, service);
230 else
231 purple_debug_warning("disco", "Cannot expand %s for account %s, "
232 "protocol did not provide expand op.\n",
233 service->name,
234 purple_account_get_username(list->account));
235 }
236
237 void purple_disco_service_register(PurpleDiscoService *service)
238 {
239 PurpleDiscoList *list;
240 PurpleConnection *pc;
241
242 g_return_if_fail(service != NULL);
243
244 list = service->list;
245 pc = purple_account_get_connection(list->account);
246
247 g_return_if_fail(pc != NULL);
248
249 if (list->ops.register_cb)
250 list->ops.register_cb(pc, service);
251 else
252 purple_debug_warning("disco", "Cannot register to %s for account %s, "
253 "protocol did not provide register op.\n",
254 service->name,
255 purple_account_get_username(list->account));
256 }
257
258 const gchar *purple_disco_service_get_name(PurpleDiscoService *service)
259 {
260 g_return_val_if_fail(service != NULL, NULL);
261
262 return service->name;
263 }
264
265 const gchar *purple_disco_service_get_description(PurpleDiscoService *service)
266 {
267 g_return_val_if_fail(service != NULL, NULL);
268
269 return service->description;
270 }
271
272 gpointer
273 purple_disco_service_get_protocol_data(PurpleDiscoService *service)
274 {
275 g_return_val_if_fail(service != NULL, NULL);
276
277 return service->proto_data;
278 }
279
280 PurpleDiscoServiceType
281 purple_disco_service_get_type(PurpleDiscoService *service)
282 {
283 g_return_val_if_fail(service != NULL, PURPLE_DISCO_SERVICE_TYPE_UNSET);
284
285 return service->type;
286 }
287
288 PurpleDiscoServiceFlags
289 purple_disco_service_get_flags(PurpleDiscoService *service)
290 {
291 g_return_val_if_fail(service != NULL, PURPLE_DISCO_NONE);
292
293 return service->flags;
294 }
295
296 void purple_disco_service_set_gateway_type(PurpleDiscoService *service, const gchar *type)
297 {
298 g_return_if_fail(service != NULL);
299
300 g_free(service->gateway_type);
301 service->gateway_type = g_strdup(type);
302 }
303
304 const gchar *purple_disco_service_get_gateway_type(PurpleDiscoService *service)
305 {
306 g_return_val_if_fail(service != NULL, NULL);
307
308 return service->gateway_type;
309 }
310
311 PurpleAccount* purple_disco_list_get_account(PurpleDiscoList *list)
312 {
313 g_return_val_if_fail(list != NULL, NULL);
314
315 return list->account;
316 }
317
318 GList* purple_disco_list_get_services(PurpleDiscoList *list)
319 {
320 g_return_val_if_fail(list != NULL, NULL);
321
322 return list->services;
323 }
324
325 void purple_disco_list_set_ui_data(PurpleDiscoList *list, gpointer ui_data)
326 {
327 g_return_if_fail(list != NULL);
328
329 list->ui_data = ui_data;
330 }
331
332 gpointer purple_disco_list_get_ui_data(PurpleDiscoList *list)
333 {
334 g_return_val_if_fail(list != NULL, NULL);
335
336 return list->ui_data;
337 }
338
339 void purple_disco_list_set_in_progress(PurpleDiscoList *list,
340 gboolean in_progress)
341 {
342 g_return_if_fail(list != NULL);
343
344 list->in_progress = in_progress;
345
346 if (ops && ops->in_progress)
347 ops->in_progress(list, in_progress);
348 }
349
350 gboolean purple_disco_list_get_in_progress(PurpleDiscoList *list)
351 {
352 g_return_val_if_fail(list != NULL, FALSE);
353
354 return list->in_progress;
355 }
356
357 void purple_disco_list_set_protocol_data(PurpleDiscoList *list,
358 gpointer proto_data,
359 PurpleDiscoCloseFunc cb)
360 {
361 g_return_if_fail(list != NULL);
362
363 list->proto_data = proto_data;
364 list->ops.close_cb = cb;
365 }
366
367 gpointer purple_disco_list_get_protocol_data(PurpleDiscoList *list)
368 {
369 g_return_val_if_fail(list != NULL, NULL);
370
371 return list->proto_data;
372 }
373
374 void purple_disco_list_set_service_close_func(PurpleDiscoList *list,
375 PurpleDiscoServiceCloseFunc cb)
376 {
377 g_return_if_fail(list != NULL);
378
379 list->ops.service_close_cb = cb;
380 }
381
382 void purple_disco_list_set_cancel_func(PurpleDiscoList *list, PurpleDiscoCancelFunc cb)
383 {
384 g_return_if_fail(list != NULL);
385
386 list->ops.cancel_cb = cb;
387 }
388
389 void purple_disco_list_set_expand_func(PurpleDiscoList *list, PurpleDiscoServiceExpandFunc cb)
390 {
391 g_return_if_fail(list != NULL);
392
393 list->ops.expand_cb = cb;
394 }
395
396 void purple_disco_list_set_register_func(PurpleDiscoList *list, PurpleDiscoRegisterFunc cb)
397 {
398 g_return_if_fail(list != NULL);
399
400 list->ops.register_cb = cb;
401 }
402
403 void purple_disco_set_ui_ops(PurpleDiscoUiOps *ui_ops)
404 {
405 ops = ui_ops;
406 }
407
408 PurpleDiscoUiOps *purple_disco_get_ui_ops(void)
409 {
410 return ops;
411 }