comparison src/dbus-server.c @ 13963:f7cfaee79982

[gaim-migrate @ 16517] Whitespace McFixen. Also, I think I'm listening to a duet of the song "One" performed by Bono and Mary J. Blige? committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Tue, 18 Jul 2006 07:18:05 +0000
parents 2d6f7ac4b6f2
children dabbcb9b013d
comparison
equal deleted inserted replaced
13962:b43aec5fa9eb 13963:f7cfaee79982
43 43
44 /**************************************************************************/ 44 /**************************************************************************/
45 /** @name Gaim DBUS pointer registration mechanism */ 45 /** @name Gaim DBUS pointer registration mechanism */
46 /**************************************************************************/ 46 /**************************************************************************/
47 47
48 /* 48 /*
49 Here we include the list of #GAIM_DBUS_DEFINE_TYPE statements for 49 * Here we include the list of #GAIM_DBUS_DEFINE_TYPE statements for
50 all structs defined in gaim. This file has been generated by the 50 * all structs defined in gaim. This file has been generated by the
51 #dbus-analize-types.py script. 51 * #dbus-analize-types.py script.
52 */ 52 */
53 53
54 #include "dbus-types.c" 54 #include "dbus-types.c"
55 55
56 /* The following three hashtables map are used to translate between 56 /*
57 pointers (nodes) and the corresponding handles (ids). */ 57 * The following three hashtables map are used to translate between
58 58 * pointers (nodes) and the corresponding handles (ids).
59 static GHashTable *map_node_id; 59 */
60 static GHashTable *map_id_node; 60
61 static GHashTable *map_id_type; 61 static GHashTable *map_node_id;
62 static GHashTable *map_id_node;
63 static GHashTable *map_id_type;
62 64
63 static gchar *init_error; 65 static gchar *init_error;
64 66
65 67 /**
66 /* This function initializes the pointer-id traslation system. It 68 * This function initializes the pointer-id traslation system. It
67 creates the three above hashtables and defines parents of some types. 69 * creates the three above hashtables and defines parents of some types.
68 */ 70 */
69 void gaim_dbus_init_ids(void) { 71 void
70 map_id_node = g_hash_table_new (g_direct_hash, g_direct_equal); 72 gaim_dbus_init_ids(void)
71 map_id_type = g_hash_table_new (g_direct_hash, g_direct_equal); 73 {
72 map_node_id = g_hash_table_new (g_direct_hash, g_direct_equal); 74 map_id_node = g_hash_table_new(g_direct_hash, g_direct_equal);
73 75 map_id_type = g_hash_table_new(g_direct_hash, g_direct_equal);
74 GAIM_DBUS_TYPE(GaimBuddy)->parent = GAIM_DBUS_TYPE(GaimBlistNode); 76 map_node_id = g_hash_table_new(g_direct_hash, g_direct_equal);
75 GAIM_DBUS_TYPE(GaimContact)->parent = GAIM_DBUS_TYPE(GaimBlistNode); 77
76 GAIM_DBUS_TYPE(GaimChat)->parent = GAIM_DBUS_TYPE(GaimBlistNode); 78 GAIM_DBUS_TYPE(GaimBuddy)->parent = GAIM_DBUS_TYPE(GaimBlistNode);
77 GAIM_DBUS_TYPE(GaimGroup)->parent = GAIM_DBUS_TYPE(GaimBlistNode); 79 GAIM_DBUS_TYPE(GaimContact)->parent = GAIM_DBUS_TYPE(GaimBlistNode);
78 } 80 GAIM_DBUS_TYPE(GaimChat)->parent = GAIM_DBUS_TYPE(GaimBlistNode);
79 81 GAIM_DBUS_TYPE(GaimGroup)->parent = GAIM_DBUS_TYPE(GaimBlistNode);
80 void gaim_dbus_register_pointer(gpointer node, GaimDBusType *type) 82 }
81 { 83
82 static gint last_id = 0; 84 void
83 85 gaim_dbus_register_pointer(gpointer node, GaimDBusType *type)
84 g_return_if_fail(map_node_id); 86 {
85 g_return_if_fail(g_hash_table_lookup(map_node_id, node) == NULL); 87 static gint last_id = 0;
86 88
87 last_id++; 89 g_return_if_fail(map_node_id);
88 g_hash_table_insert(map_node_id, node, GINT_TO_POINTER(last_id)); 90 g_return_if_fail(g_hash_table_lookup(map_node_id, node) == NULL);
89 g_hash_table_insert(map_id_node, GINT_TO_POINTER(last_id), node); 91
90 g_hash_table_insert(map_id_type, GINT_TO_POINTER(last_id), type); 92 last_id++;
91 } 93 g_hash_table_insert(map_node_id, node, GINT_TO_POINTER(last_id));
92 94 g_hash_table_insert(map_id_node, GINT_TO_POINTER(last_id), node);
93 void gaim_dbus_unregister_pointer(gpointer node) { 95 g_hash_table_insert(map_id_type, GINT_TO_POINTER(last_id), type);
94 gpointer id = g_hash_table_lookup(map_node_id, node); 96 }
95 97
96 g_hash_table_remove(map_node_id, node); 98 void
97 g_hash_table_remove(map_id_node, GINT_TO_POINTER(id)); 99 gaim_dbus_unregister_pointer(gpointer node)
98 g_hash_table_remove(map_id_type, GINT_TO_POINTER(id)); 100 {
99 } 101 gpointer id = g_hash_table_lookup(map_node_id, node);
100 102
101 gint gaim_dbus_pointer_to_id(gpointer node) { 103 g_hash_table_remove(map_node_id, node);
102 gint id = GPOINTER_TO_INT(g_hash_table_lookup(map_node_id, node)); 104 g_hash_table_remove(map_id_node, GINT_TO_POINTER(id));
105 g_hash_table_remove(map_id_type, GINT_TO_POINTER(id));
106 }
107
108 gint
109 gaim_dbus_pointer_to_id(gpointer node)
110 {
111 gint id = GPOINTER_TO_INT(g_hash_table_lookup(map_node_id, node));
103 if ((id == 0) && (node != NULL)) 112 if ((id == 0) && (node != NULL))
104 { 113 {
105 gaim_debug_warning("dbus", 114 gaim_debug_warning("dbus",
106 "Need to register an object with the dbus subsystem.\n"); 115 "Need to register an object with the dbus subsystem.\n");
107 g_return_val_if_reached(0); 116 g_return_val_if_reached(0);
108 } 117 }
109 return id; 118 return id;
110 } 119 }
111 120
112 gpointer gaim_dbus_id_to_pointer(gint id, GaimDBusType *type) { 121 gpointer
113 GaimDBusType *objtype = 122 gaim_dbus_id_to_pointer(gint id, GaimDBusType *type)
114 (GaimDBusType*) g_hash_table_lookup(map_id_type, 123 {
115 GINT_TO_POINTER(id)); 124 GaimDBusType *objtype;
116 125
117 while (objtype != type && objtype != NULL) 126 objtype = (GaimDBusType*)g_hash_table_lookup(map_id_type,
118 objtype = objtype->parent; 127 GINT_TO_POINTER(id));
119 128
120 if (objtype == type) 129 while (objtype != type && objtype != NULL)
121 return g_hash_table_lookup(map_id_node, GINT_TO_POINTER(id)); 130 objtype = objtype->parent;
122 else 131
123 return NULL; 132 if (objtype == type)
124 } 133 return g_hash_table_lookup(map_id_node, GINT_TO_POINTER(id));
125 134 else
126 gint gaim_dbus_pointer_to_id_error(gpointer ptr, DBusError *error) 135 return NULL;
127 { 136 }
128 gint id = gaim_dbus_pointer_to_id(ptr); 137
129 138 gint
130 if (ptr != NULL && id == 0) 139 gaim_dbus_pointer_to_id_error(gpointer ptr, DBusError *error)
131 dbus_set_error(error, "net.sf.gaim.ObjectNotFound", 140 {
132 "The return object is not mapped (this is a Gaim error)"); 141 gint id = gaim_dbus_pointer_to_id(ptr);
133 142
134 return id; 143 if (ptr != NULL && id == 0)
135 } 144 dbus_set_error(error, "net.sf.gaim.ObjectNotFound",
136 145 "The return object is not mapped (this is a Gaim error)");
137 gpointer gaim_dbus_id_to_pointer_error(gint id, GaimDBusType *type, 146
138 const char *typename, DBusError *error) 147 return id;
139 { 148 }
140 gpointer ptr = gaim_dbus_id_to_pointer(id, type); 149
141 150 gpointer
142 if (ptr == NULL && id != 0) 151 gaim_dbus_id_to_pointer_error(gint id, GaimDBusType *type,
143 dbus_set_error(error, "net.sf.gaim.InvalidHandle", 152 const char *typename, DBusError *error)
144 "%s object with ID = %i not found", typename, id); 153 {
145 154 gpointer ptr = gaim_dbus_id_to_pointer(id, type);
146 return ptr; 155
156 if (ptr == NULL && id != 0)
157 dbus_set_error(error, "net.sf.gaim.InvalidHandle",
158 "%s object with ID = %i not found", typename, id);
159
160 return ptr;
147 } 161 }
148 162
149 163
150 /**************************************************************************/ 164 /**************************************************************************/
151 /** @name Modified versions of some DBus functions */ 165 /** @name Modified versions of some DBus functions */
152 /**************************************************************************/ 166 /**************************************************************************/
153 167
154 dbus_bool_t 168 dbus_bool_t
155 gaim_dbus_message_get_args (DBusMessage *message, 169 gaim_dbus_message_get_args(DBusMessage *message,
156 DBusError *error, 170 DBusError *error, int first_arg_type, ...)
157 int first_arg_type, 171 {
158 ...) 172 dbus_bool_t retval;
159 { 173 va_list var_args;
160 dbus_bool_t retval; 174
161 va_list var_args; 175 va_start(var_args, first_arg_type);
162 176 retval = gaim_dbus_message_get_args_valist(message, error, first_arg_type, var_args);
163 va_start (var_args, first_arg_type); 177 va_end(var_args);
164 retval = gaim_dbus_message_get_args_valist (message, error, first_arg_type, var_args); 178
165 va_end (var_args); 179 return retval;
166
167 return retval;
168 } 180 }
169 181
170 dbus_bool_t 182 dbus_bool_t
171 gaim_dbus_message_get_args_valist (DBusMessage *message, 183 gaim_dbus_message_get_args_valist(DBusMessage *message,
172 DBusError *error, 184 DBusError *error, int first_arg_type, va_list var_args)
173 int first_arg_type, 185 {
174 va_list var_args) 186 DBusMessageIter iter;
175 { 187
176 DBusMessageIter iter; 188 dbus_message_iter_init(message, &iter);
177 189 return gaim_dbus_message_iter_get_args_valist(&iter, error, first_arg_type, var_args);
178 dbus_message_iter_init (message, &iter);
179 return gaim_dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
180 } 190 }
181 191
182 dbus_bool_t 192 dbus_bool_t
183 gaim_dbus_message_iter_get_args(DBusMessageIter *iter, 193 gaim_dbus_message_iter_get_args(DBusMessageIter *iter,
184 DBusError *error, 194 DBusError *error, int first_arg_type, ...)
185 int first_arg_type, 195 {
186 ...) 196 dbus_bool_t retval;
187 { 197 va_list var_args;
188 dbus_bool_t retval; 198
189 va_list var_args; 199 va_start(var_args, first_arg_type);
190 200 retval = gaim_dbus_message_iter_get_args_valist(iter, error, first_arg_type, var_args);
191 va_start (var_args, first_arg_type); 201 va_end(var_args);
192 retval = gaim_dbus_message_iter_get_args_valist(iter, error, first_arg_type, var_args); 202
193 va_end (var_args); 203 return retval;
194 204 }
195 return retval; 205
196 } 206 #define TYPE_IS_CONTAINER(typecode) \
197 207 ((typecode) == DBUS_TYPE_STRUCT || \
198 #define TYPE_IS_CONTAINER(typecode) \ 208 (typecode) == DBUS_TYPE_DICT_ENTRY || \
199 ((typecode) == DBUS_TYPE_STRUCT || \ 209 (typecode) == DBUS_TYPE_VARIANT || \
200 (typecode) == DBUS_TYPE_DICT_ENTRY || \ 210 (typecode) == DBUS_TYPE_ARRAY)
201 (typecode) == DBUS_TYPE_VARIANT || \
202 (typecode) == DBUS_TYPE_ARRAY)
203 211
204 212
205 dbus_bool_t 213 dbus_bool_t
206 gaim_dbus_message_iter_get_args_valist (DBusMessageIter *iter, 214 gaim_dbus_message_iter_get_args_valist(DBusMessageIter *iter,
207 DBusError *error, 215 DBusError *error, int first_arg_type, va_list var_args)
208 int first_arg_type, 216 {
209 va_list var_args) 217 int spec_type, msg_type, i;
210 { 218
211 int spec_type, msg_type, i; 219 spec_type = first_arg_type;
212 220
213 spec_type = first_arg_type; 221 for (i = 0; spec_type != DBUS_TYPE_INVALID; i++)
214 222 {
215 for(i=0; spec_type != DBUS_TYPE_INVALID; i++) { 223 msg_type = dbus_message_iter_get_arg_type(iter);
216 msg_type = dbus_message_iter_get_arg_type (iter); 224
217 225 if (msg_type != spec_type)
218 if (msg_type != spec_type) { 226 {
219 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 227 dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
220 "Argument %d is specified to be of type \"%i\", but " 228 "Argument %d is specified to be of type \"%i\", but "
221 "is actually of type \"%i\"\n", i, 229 "is actually of type \"%i\"\n", i,
222 spec_type, msg_type); 230 spec_type, msg_type);
223 return FALSE; 231 return FALSE;
232 }
233
234 if (!TYPE_IS_CONTAINER(spec_type))
235 {
236 gpointer ptr;
237 ptr = va_arg (var_args, gpointer);
238 dbus_message_iter_get_basic(iter, ptr);
239 }
240 else
241 {
242 DBusMessageIter *sub;
243 sub = va_arg (var_args, DBusMessageIter*);
244 dbus_message_iter_recurse(iter, sub);
245 gaim_debug_info("dbus", "subiter %p:%p\n", sub, * (gpointer*) sub);
246 break; /* for testing only! */
247 }
248
249 spec_type = va_arg(var_args, int);
250 if (!dbus_message_iter_next(iter) && spec_type != DBUS_TYPE_INVALID)
251 {
252 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
253 "Message has only %d arguments, but more were expected", i);
254 return FALSE;
255 }
224 } 256 }
225 257
226 if (!TYPE_IS_CONTAINER(spec_type)) { 258 return TRUE;
227 gpointer ptr;
228 ptr = va_arg (var_args, gpointer);
229 dbus_message_iter_get_basic(iter, ptr);
230 }
231 else {
232 DBusMessageIter *sub;
233 sub = va_arg (var_args, DBusMessageIter*);
234 dbus_message_iter_recurse(iter, sub);
235 gaim_debug_info("dbus", "subiter %p:%p\n", sub, * (gpointer*) sub);
236 break; /* for testing only! */
237 }
238
239 spec_type = va_arg (var_args, int);
240 if (!dbus_message_iter_next(iter) && spec_type != DBUS_TYPE_INVALID) {
241 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
242 "Message has only %d arguments, but more were expected", i);
243 return FALSE;
244 }
245 }
246 return TRUE;
247 } 259 }
248 260
249 261
250 262
251 /**************************************************************************/ 263 /**************************************************************************/
252 /** @name Useful functions */ 264 /** @name Useful functions */
253 /**************************************************************************/ 265 /**************************************************************************/
254 266
255 const char* empty_to_null(const char *str) { 267 const char *empty_to_null(const char *str)
256 if (str == NULL || str[0] == 0) 268 {
257 return NULL; 269 if (str == NULL || str[0] == 0)
258 else 270 return NULL;
259 return str; 271 else
260 } 272 return str;
261 273 }
262 const char* null_to_empty(const char *s) { 274
275 const char *
276 null_to_empty(const char *s)
277 {
263 if (s) 278 if (s)
264 return s; 279 return s;
265 else 280 else
266 return ""; 281 return "";
267 } 282 }
268 283
269 dbus_int32_t* gaim_dbusify_GList(GList *list, gboolean free_memory, 284 dbus_int32_t *
270 dbus_int32_t *len) 285 gaim_dbusify_GList(GList *list, gboolean free_memory, dbus_int32_t *len)
271 { 286 {
272 dbus_int32_t *array; 287 dbus_int32_t *array;
273 int i; 288 int i;
274 GList *elem; 289 GList *elem;
275 290
276 *len = g_list_length(list); 291 *len = g_list_length(list);
277 array = g_new0(dbus_int32_t, g_list_length(list)); 292 array = g_new0(dbus_int32_t, g_list_length(list));
278 for(i = 0, elem = list; elem != NULL; elem = elem->next, i++) 293 for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
279 array[i] = gaim_dbus_pointer_to_id(elem->data); 294 array[i] = gaim_dbus_pointer_to_id(elem->data);
280 295
281 if (free_memory) 296 if (free_memory)
282 g_list_free(list); 297 g_list_free(list);
283 298
284 return array; 299 return array;
285 } 300 }
286 301
287 dbus_int32_t* gaim_dbusify_GSList(GSList *list, gboolean free_memory, 302 dbus_int32_t *
288 dbus_int32_t *len) 303 gaim_dbusify_GSList(GSList *list, gboolean free_memory, dbus_int32_t *len)
289 { 304 {
290 dbus_int32_t *array; 305 dbus_int32_t *array;
291 int i; 306 int i;
292 GSList *elem; 307 GSList *elem;
293 308
294 *len = g_slist_length(list); 309 *len = g_slist_length(list);
295 array = g_new0(dbus_int32_t, g_slist_length(list)); 310 array = g_new0(dbus_int32_t, g_slist_length(list));
296 for(i = 0, elem = list; elem != NULL; elem = elem->next, i++) 311 for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
297 array[i] = gaim_dbus_pointer_to_id(elem->data); 312 array[i] = gaim_dbus_pointer_to_id(elem->data);
298 313
299 if (free_memory) 314 if (free_memory)
300 g_slist_free(list); 315 g_slist_free(list);
301 316
302 return array; 317 return array;
303 } 318 }
304 319
305 gpointer* gaim_GList_to_array(GList *list, gboolean free_memory, 320 gpointer *
306 dbus_int32_t *len) 321 gaim_GList_to_array(GList *list, gboolean free_memory, dbus_int32_t *len)
307 { 322 {
308 gpointer *array; 323 gpointer *array;
309 int i; 324 int i;
310 GList *elem; 325 GList *elem;
311 326
312 *len = g_list_length(list); 327 *len = g_list_length(list);
313 array = g_new0(gpointer, g_list_length(list)); 328 array = g_new0(gpointer, g_list_length(list));
314 for(i = 0, elem = list; elem != NULL; elem = elem->next, i++) 329 for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
315 array[i] = elem->data; 330 array[i] = elem->data;
316 331
317 if (free_memory) 332 if (free_memory)
318 g_list_free(list); 333 g_list_free(list);
319 334
320 return array; 335 return array;
321 } 336 }
322 337
323 gpointer* gaim_GSList_to_array(GSList *list, gboolean free_memory, 338 gpointer *
324 dbus_int32_t *len) 339 gaim_GSList_to_array(GSList *list, gboolean free_memory, dbus_int32_t *len)
325 { 340 {
326 gpointer *array; 341 gpointer *array;
327 int i; 342 int i;
328 GSList *elem; 343 GSList *elem;
329 344
330 *len = g_slist_length(list); 345 *len = g_slist_length(list);
331 array = g_new0(gpointer, g_slist_length(list)); 346 array = g_new0(gpointer, g_slist_length(list));
332 for(i = 0, elem = list; elem != NULL; elem = elem->next, i++) 347 for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
333 array[i] = elem->data; 348 array[i] = elem->data;
334 349
335 if (free_memory) 350 if (free_memory)
336 g_slist_free(list); 351 g_slist_free(list);
337 352
338 return array; 353 return array;
339 } 354 }
340 355
341 GHashTable *gaim_dbus_iter_hash_table(DBusMessageIter *iter, DBusError *error) { 356 GHashTable *
342 GHashTable *hash; 357 gaim_dbus_iter_hash_table(DBusMessageIter *iter, DBusError *error)
343 358 {
344 /* we do not need to destroy strings because they are part of the message */ 359 GHashTable *hash;
345 hash = g_hash_table_new(g_str_hash, g_str_equal); 360
346 361 /* we do not need to destroy strings because they are part of the message */
347 do { 362 hash = g_hash_table_new(g_str_hash, g_str_equal);
348 char *key, *value; 363
349 DBusMessageIter subiter; 364 do {
350 365 char *key, *value;
351 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) 366 DBusMessageIter subiter;
352 goto error; /* With all due respect to Dijkstra, 367
353 this goto is for exception 368 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
354 handling, and it is ok because it 369 goto error;
355 avoids duplication of the code 370 /* With all due respect to Dijkstra,
356 responsible for destroying the hash 371 * this goto is for exception
357 table. Exceptional instructions 372 * handling, and it is ok because it
358 for exceptional situations. */ 373 * avoids duplication of the code
359 374 * responsible for destroying the hash
360 dbus_message_iter_recurse(iter, &subiter); 375 * table. Exceptional instructions
361 if (!gaim_dbus_message_iter_get_args(&subiter, error, 376 * for exceptional situations.
362 DBUS_TYPE_STRING, &key, 377 */
363 DBUS_TYPE_STRING, &value, 378
364 DBUS_TYPE_INVALID)) 379 dbus_message_iter_recurse(iter, &subiter);
365 goto error; /* same here */ 380 if (!gaim_dbus_message_iter_get_args(&subiter, error,
366 381 DBUS_TYPE_STRING, &key,
367 g_hash_table_insert(hash, key, value); 382 DBUS_TYPE_STRING, &value,
368 } while (dbus_message_iter_next(iter)); 383 DBUS_TYPE_INVALID))
369 384 goto error; /* same here */
370 return hash; 385
371 386 g_hash_table_insert(hash, key, value);
372 error: 387 } while (dbus_message_iter_next(iter));
373 g_hash_table_destroy(hash); 388
374 return NULL; 389 return hash;
390
391 error:
392 g_hash_table_destroy(hash);
393 return NULL;
375 } 394 }
376 395
377 /**************************************************************/ 396 /**************************************************************/
378 /* DBus bindings ... */ 397 /* DBus bindings ... */
379 /**************************************************************/ 398 /**************************************************************/
380 399
381 static DBusConnection *gaim_dbus_connection; 400 static DBusConnection *gaim_dbus_connection;
382 401
383 DBusConnection *gaim_dbus_get_connection(void) { 402 DBusConnection *
384 return gaim_dbus_connection; 403 gaim_dbus_get_connection(void)
404 {
405 return gaim_dbus_connection;
385 } 406 }
386 407
387 #include "dbus-bindings.c" 408 #include "dbus-bindings.c"
388 409
389 static gboolean 410 static gboolean
390 gaim_dbus_dispatch_cb(DBusConnection *connection, 411 gaim_dbus_dispatch_cb(DBusConnection *connection,
391 DBusMessage *message, 412 DBusMessage *message, void *user_data)
392 void *user_data) 413 {
393 { 414 const char *name;
394 const char *name; 415 GaimDBusBinding *bindings;
395 GaimDBusBinding *bindings; 416 int i;
396 int i; 417
397 418 bindings = (GaimDBusBinding*) user_data;
398 bindings = (GaimDBusBinding*) user_data; 419
399 420 if (!dbus_message_has_path(message, DBUS_PATH_GAIM))
400 if (!dbus_message_has_path(message, DBUS_PATH_GAIM)) 421 return FALSE;
422
423 name = dbus_message_get_member(message);
424
425 if (name == NULL)
426 return FALSE;
427
428 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
429 return FALSE;
430
431 for (i = 0; bindings[i].name; i++)
432 if (!strcmp(name, bindings[i].name))
433 {
434 DBusMessage *reply;
435 DBusError error;
436
437 dbus_error_init(&error);
438
439 reply = bindings[i].handler(message, &error);
440
441 if (reply == NULL && dbus_error_is_set(&error))
442 reply = dbus_message_new_error (message,
443 error.name, error.message);
444
445 if (reply != NULL)
446 {
447 dbus_connection_send(connection, reply, NULL);
448 dbus_message_unref(reply);
449 }
450
451 return TRUE; /* return reply! */
452 }
453
401 return FALSE; 454 return FALSE;
402 455 }
403 name = dbus_message_get_member(message); 456
404 457
405 if (name == NULL) 458 static const char *
406 return FALSE; 459 dbus_gettext(const char **ptr)
407 460 {
408 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL) 461 const char *text = *ptr;
409 return FALSE; 462 *ptr += strlen(text) + 1;
410 463 return text;
411 for(i=0; bindings[i].name; i++) 464 }
412 if (!strcmp(name, bindings[i].name)) { 465
413 DBusMessage *reply; 466 static void
414 DBusError error; 467 gaim_dbus_introspect_cb(GList **bindings_list, void *bindings)
415 468 {
416 dbus_error_init(&error); 469 *bindings_list = g_list_prepend(*bindings_list, bindings);
417 470 }
418 reply = bindings[i].handler(message, &error); 471
419 472 static DBusMessage *gaim_dbus_introspect(DBusMessage *message)
420 if (reply == NULL && dbus_error_is_set(&error)) 473 {
421 reply = dbus_message_new_error (message, 474 DBusMessage *reply;
422 error.name, 475 GString *str;
423 error.message); 476 GList *bindings_list, *node;
424 477
425 if (reply != NULL) { 478 str = g_string_sized_new(0x1000); /* TODO: why this size? */
479
480 g_string_append(str, "<!DOCTYPE node PUBLIC '-//freedesktop//DTD D-BUS Object Introspection 1.0//EN' 'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>\n");
481 g_string_append_printf(str, "<node name='%s'>\n", DBUS_PATH_GAIM);
482 g_string_append_printf(str, "<interface name='%s'>\n", DBUS_INTERFACE_GAIM);
483
484 bindings_list = NULL;
485 gaim_signal_emit(gaim_dbus_get_handle(), "dbus-introspect", &bindings_list);
486
487 for (node = bindings_list; node; node = node->next)
488 {
489 GaimDBusBinding *bindings;
490 int i;
491
492 bindings = (GaimDBusBinding*)node->data;
493
494 for (i = 0; bindings[i].name; i++)
495 {
496 const char *text;
497
498 g_string_append_printf(str, "<method name='%s'>\n", bindings[i].name);
499
500 text = bindings[i].parameters;
501 while (*text)
502 {
503 const char *name, *direction, *type;
504
505 direction = dbus_gettext(&text);
506 type = dbus_gettext(&text);
507 name = dbus_gettext(&text);
508
509 g_string_append_printf(str,
510 "<arg name='%s' type='%s' direction='%s'/>\n",
511 name, type, direction);
512 }
513 g_string_append(str, "</method>\n");
514 }
515 }
516
517 g_string_append(str, "</interface>\n</node>\n");
518
519 reply = dbus_message_new_method_return(message);
520 dbus_message_append_args(reply, DBUS_TYPE_STRING, &(str->str),
521 DBUS_TYPE_INVALID);
522 g_string_free(str, TRUE);
523 g_list_free(bindings_list);
524
525 return reply;
526 }
527
528 static DBusHandlerResult
529 gaim_dbus_dispatch(DBusConnection *connection,
530 DBusMessage *message, void *user_data)
531 {
532 if (gaim_signal_emit_return_1(gaim_dbus_get_handle(),
533 "dbus-method-called", connection, message))
534 return DBUS_HANDLER_RESULT_HANDLED;
535
536 if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL &&
537 dbus_message_has_path(message, DBUS_PATH_GAIM) &&
538 dbus_message_has_interface(message, DBUS_INTERFACE_INTROSPECTABLE) &&
539 dbus_message_has_member(message, "Introspect"))
540 {
541 DBusMessage *reply;
542 reply = gaim_dbus_introspect(message);
426 dbus_connection_send (connection, reply, NULL); 543 dbus_connection_send (connection, reply, NULL);
427 dbus_message_unref(reply); 544 dbus_message_unref(reply);
428 } 545 return DBUS_HANDLER_RESULT_HANDLED;
429
430 return TRUE; /* return reply! */
431 } 546 }
432 547
433 return FALSE; 548 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
434 } 549 }
435 550
436 551 void
437 static const char *dbus_gettext(const char **ptr) { 552 gaim_dbus_register_bindings(void *handle, GaimDBusBinding *bindings)
438 const char *text = *ptr; 553 {
439 *ptr += strlen(text) + 1; 554 gaim_signal_connect(gaim_dbus_get_handle(), "dbus-method-called",
440 return text; 555 handle,
441 }
442
443 static void
444 gaim_dbus_introspect_cb(GList **bindings_list, void *bindings) {
445 *bindings_list = g_list_prepend(*bindings_list, bindings);
446 }
447
448 static DBusMessage *gaim_dbus_introspect(DBusMessage *message)
449 {
450 DBusMessage *reply;
451 GString *str;
452 GList *bindings_list, *node;
453
454 str = g_string_sized_new(0x1000); /* fixme: why this size? */
455
456 g_string_append(str, "<!DOCTYPE node PUBLIC '-//freedesktop//DTD D-BUS Object Introspection 1.0//EN' 'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>\n");
457 g_string_append_printf(str, "<node name='%s'>\n", DBUS_PATH_GAIM);
458 g_string_append_printf(str, "<interface name='%s'>\n", DBUS_INTERFACE_GAIM);
459
460 bindings_list = NULL;
461 gaim_signal_emit(gaim_dbus_get_handle(), "dbus-introspect", &bindings_list);
462
463 for(node = bindings_list; node; node = node->next) {
464 GaimDBusBinding *bindings;
465 int i;
466
467 bindings = (GaimDBusBinding*) node->data;
468
469 for(i=0; bindings[i].name; i++) {
470 const char *text;
471
472 g_string_append_printf(str, "<method name='%s'>\n", bindings[i].name);
473
474 text = bindings[i].parameters;
475 while (*text) {
476 const char *name, *direction, *type;
477
478 direction = dbus_gettext(&text);
479 type = dbus_gettext(&text);
480 name = dbus_gettext(&text);
481
482 g_string_append_printf(str,
483 "<arg name='%s' type='%s' direction='%s'/>\n",
484 name, type, direction);
485 }
486 g_string_append(str, "</method>\n");
487 }
488 }
489
490 g_string_append(str, "</interface>\n</node>\n");
491
492 reply = dbus_message_new_method_return (message);
493 dbus_message_append_args(reply, DBUS_TYPE_STRING, &(str->str),
494 DBUS_TYPE_INVALID);
495 g_string_free(str, TRUE);
496 g_list_free(bindings_list);
497
498 return reply;
499
500 }
501
502 static DBusHandlerResult gaim_dbus_dispatch(DBusConnection *connection,
503 DBusMessage *message,
504 void *user_data)
505 {
506 if (gaim_signal_emit_return_1(gaim_dbus_get_handle(),
507 "dbus-method-called",
508 connection, message))
509 return DBUS_HANDLER_RESULT_HANDLED;
510
511 if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL &&
512 dbus_message_has_path(message, DBUS_PATH_GAIM) &&
513 dbus_message_has_interface(message, DBUS_INTERFACE_INTROSPECTABLE) &&
514 dbus_message_has_member(message, "Introspect"))
515 {
516 DBusMessage *reply;
517 reply = gaim_dbus_introspect(message);
518 dbus_connection_send (connection, reply, NULL);
519 dbus_message_unref(reply);
520 return DBUS_HANDLER_RESULT_HANDLED;
521 }
522
523 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
524 }
525
526 void gaim_dbus_register_bindings(void *handle, GaimDBusBinding *bindings) {
527 gaim_signal_connect(gaim_dbus_get_handle(), "dbus-method-called",
528 handle,
529 GAIM_CALLBACK(gaim_dbus_dispatch_cb), 556 GAIM_CALLBACK(gaim_dbus_dispatch_cb),
530 bindings); 557 bindings);
531 gaim_signal_connect(gaim_dbus_get_handle(), "dbus-introspect", 558 gaim_signal_connect(gaim_dbus_get_handle(), "dbus-introspect",
532 handle, 559 handle,
533 GAIM_CALLBACK(gaim_dbus_introspect_cb), 560 GAIM_CALLBACK(gaim_dbus_introspect_cb),
534 bindings); 561 bindings);
535 } 562 }
536 563
537 564 static void
538 565 gaim_dbus_dispatch_init(void)
539 static void gaim_dbus_dispatch_init(void) 566 {
540 { 567 static DBusObjectPathVTable vtable = {NULL, &gaim_dbus_dispatch, NULL, NULL, NULL, NULL};
541 static DBusObjectPathVTable vtable = {NULL, &gaim_dbus_dispatch, NULL, NULL, NULL, NULL}; 568 DBusError error;
542 569 int result;
543 DBusError error; 570
544 int result; 571 dbus_error_init(&error);
545 572 gaim_dbus_connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
546 dbus_error_init (&error); 573
547 gaim_dbus_connection = dbus_bus_get (DBUS_BUS_STARTER, &error); 574 if (gaim_dbus_connection == NULL)
548 575 {
549 if (gaim_dbus_connection == NULL) { 576 init_error = g_strdup_printf(N_("Failed to get connection: %s"), error.message);
550 init_error = g_strdup_printf(N_("Failed to get connection: %s"), error.message); 577 dbus_error_free(&error);
551 dbus_error_free(&error); 578 return;
552 return; 579 }
553 } 580
554 581 if (!dbus_connection_register_object_path(gaim_dbus_connection,
555 if (!dbus_connection_register_object_path (gaim_dbus_connection, 582 DBUS_PATH_GAIM, &vtable, NULL))
556 DBUS_PATH_GAIM, &vtable, NULL)) 583 {
557 { 584 init_error = g_strdup_printf(N_("Failed to get name: %s"), error.name);
558 init_error = g_strdup_printf(N_("Failed to get name: %s"), error.name); 585 dbus_error_free(&error);
559 dbus_error_free(&error); 586 return;
560 return; 587 }
561 } 588
562 589 result = dbus_bus_request_name(gaim_dbus_connection,
563 590 DBUS_SERVICE_GAIM, 0, &error);
564 result = dbus_bus_request_name (gaim_dbus_connection, DBUS_SERVICE_GAIM, 591
565 0, &error); 592 if (dbus_error_is_set(&error))
566 593 {
567 if (dbus_error_is_set (&error)) { 594 dbus_connection_unref(gaim_dbus_connection);
568 dbus_connection_unref(gaim_dbus_connection); 595 dbus_error_free(&error);
569 dbus_error_free(&error); 596 gaim_dbus_connection = NULL;
570 gaim_dbus_connection = NULL; 597 init_error = g_strdup_printf(N_("Failed to get serv name: %s"), error.name);
571 init_error = g_strdup_printf(N_("Failed to get serv name: %s"), error.name); 598 return;
572 return; 599 }
573 } 600
574 601 dbus_connection_setup_with_g_main(gaim_dbus_connection, NULL);
575 dbus_connection_setup_with_g_main(gaim_dbus_connection, NULL); 602
576 603 gaim_debug_misc("dbus", "okkk\n");
577 gaim_debug_misc ("dbus", "okkk\n"); 604
578 605 gaim_signal_register(gaim_dbus_get_handle(), "dbus-method-called",
579 gaim_signal_register(gaim_dbus_get_handle(), "dbus-method-called",
580 gaim_marshal_BOOLEAN__POINTER_POINTER, 606 gaim_marshal_BOOLEAN__POINTER_POINTER,
581 gaim_value_new(GAIM_TYPE_BOOLEAN), 2, 607 gaim_value_new(GAIM_TYPE_BOOLEAN), 2,
582 gaim_value_new(GAIM_TYPE_POINTER), 608 gaim_value_new(GAIM_TYPE_POINTER),
583 gaim_value_new(GAIM_TYPE_POINTER)); 609 gaim_value_new(GAIM_TYPE_POINTER));
584 610
585 gaim_signal_register(gaim_dbus_get_handle(), "dbus-introspect", 611 gaim_signal_register(gaim_dbus_get_handle(), "dbus-introspect",
586 gaim_marshal_VOID__POINTER, NULL, 1, 612 gaim_marshal_VOID__POINTER, NULL, 1,
587 gaim_value_new_outgoing(GAIM_TYPE_POINTER)); 613 gaim_value_new_outgoing(GAIM_TYPE_POINTER));
588 614
589 GAIM_DBUS_REGISTER_BINDINGS(gaim_dbus_get_handle()); 615 GAIM_DBUS_REGISTER_BINDINGS(gaim_dbus_get_handle());
590 } 616 }
591 617
592 618
593 619
594 /**************************************************************************/ 620 /**************************************************************************/
595 /** @name Signals */ 621 /** @name Signals */
596 /**************************************************************************/ 622 /**************************************************************************/
597 623
598 624
599 625
600 static char *gaim_dbus_convert_signal_name(const char *gaim_name) 626 static char *
627 gaim_dbus_convert_signal_name(const char *gaim_name)
601 { 628 {
602 int gaim_index, g_index; 629 int gaim_index, g_index;
603 char *g_name = g_new(char, strlen(gaim_name)+1); 630 char *g_name = g_new(char, strlen(gaim_name) + 1);
604 gboolean capitalize_next = TRUE; 631 gboolean capitalize_next = TRUE;
605 632
606 for(gaim_index = g_index = 0; gaim_name[gaim_index]; gaim_index++) 633 for (gaim_index = g_index = 0; gaim_name[gaim_index]; gaim_index++)
607 if (gaim_name[gaim_index] != '-' && gaim_name[gaim_index] != '_') { 634 if (gaim_name[gaim_index] != '-' && gaim_name[gaim_index] != '_')
635 {
608 if (capitalize_next) 636 if (capitalize_next)
609 g_name[g_index++] = g_ascii_toupper(gaim_name[gaim_index]); 637 g_name[g_index++] = g_ascii_toupper(gaim_name[gaim_index]);
610 else 638 else
611 g_name[g_index++] = gaim_name[gaim_index]; 639 g_name[g_index++] = gaim_name[gaim_index];
612 capitalize_next = FALSE; 640 capitalize_next = FALSE;
613 } else 641 } else
614 capitalize_next = TRUE; 642 capitalize_next = TRUE;
643
615 g_name[g_index] = 0; 644 g_name[g_index] = 0;
616 645
617 return g_name; 646 return g_name;
618 } 647 }
619 648
620 #define my_arg(type) (ptr != NULL ? * ((type *)ptr) : va_arg(data, type)) 649 #define my_arg(type) (ptr != NULL ? * ((type *)ptr) : va_arg(data, type))
621 650
622 static void gaim_dbus_message_append_gaim_values(DBusMessageIter *iter, 651 static void
623 int number, 652 gaim_dbus_message_append_gaim_values(DBusMessageIter *iter,
624 GaimValue **gaim_values, 653 int number, GaimValue **gaim_values, va_list data)
625 va_list data) 654 {
626 { 655 int i;
627 int i; 656
628 657 for (i = 0; i < number; i++)
629 for(i=0; i<number; i++) { 658 {
630 const char *str; 659 const char *str;
631 int id; 660 int id;
632 gint xint; 661 gint xint;
633 guint xuint; 662 guint xuint;
634 gboolean xboolean; 663 gboolean xboolean;
635 gpointer ptr = NULL; 664 gpointer ptr = NULL;
636 if (gaim_value_is_outgoing(gaim_values[i])) { 665
637 ptr = my_arg(gpointer); 666 if (gaim_value_is_outgoing(gaim_values[i]))
638 g_return_if_fail(ptr); 667 {
668 ptr = my_arg(gpointer);
669 g_return_if_fail(ptr);
670 }
671
672 switch (gaim_values[i]->type)
673 {
674 case GAIM_TYPE_INT:
675 xint = my_arg(gint);
676 dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &xint);
677 break;
678 case GAIM_TYPE_UINT:
679 xuint = my_arg(guint);
680 dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &xuint);
681 break;
682 case GAIM_TYPE_BOOLEAN:
683 xboolean = my_arg(gboolean);
684 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &xboolean);
685 break;
686 case GAIM_TYPE_STRING:
687 str = null_to_empty(my_arg(char*));
688 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &str);
689 break;
690 case GAIM_TYPE_SUBTYPE: /* registered pointers only! */
691 case GAIM_TYPE_POINTER:
692 case GAIM_TYPE_OBJECT:
693 case GAIM_TYPE_BOXED:
694 id = gaim_dbus_pointer_to_id(my_arg(gpointer));
695 dbus_message_iter_append_basic(iter,
696 (sizeof(void *) == 4) ? DBUS_TYPE_UINT32 : DBUS_TYPE_UINT64, &id);
697 break;
698 default: /* no conversion implemented */
699 g_return_if_reached();
700 }
639 } 701 }
640
641 switch(gaim_values[i]->type) {
642 case GAIM_TYPE_INT:
643 xint = my_arg(gint);
644 dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &xint);
645 break;
646 case GAIM_TYPE_UINT:
647 xuint = my_arg(guint);
648 dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &xuint);
649 break;
650 case GAIM_TYPE_BOOLEAN:
651 xboolean = my_arg(gboolean);
652 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &xboolean);
653 break;
654 case GAIM_TYPE_STRING:
655 str = null_to_empty(my_arg(char*));
656 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &str);
657 break;
658 case GAIM_TYPE_SUBTYPE: /* registered pointers only! */
659 case GAIM_TYPE_POINTER:
660 case GAIM_TYPE_OBJECT:
661 case GAIM_TYPE_BOXED:
662 id = gaim_dbus_pointer_to_id(my_arg(gpointer));
663 dbus_message_iter_append_basic(iter, (sizeof(void *) == 4) ? DBUS_TYPE_UINT32 : DBUS_TYPE_UINT64, &id);
664 break;
665 default: /* no conversion implemented */
666 g_return_if_reached();
667 }
668 }
669 } 702 }
670 703
671 #undef my_arg 704 #undef my_arg
672 705
673 void gaim_dbus_signal_emit_gaim(const char *name, int num_values, 706 void
674 GaimValue **values, va_list vargs) 707 gaim_dbus_signal_emit_gaim(const char *name, int num_values,
675 { 708 GaimValue **values, va_list vargs)
676 DBusMessage *signal; 709 {
677 DBusMessageIter iter; 710 DBusMessage *signal;
678 char *newname; 711 DBusMessageIter iter;
712 char *newname;
679 713
680 #if 0 /* this is noisy with no dbus connection */ 714 #if 0 /* this is noisy with no dbus connection */
681 g_return_if_fail(gaim_dbus_connection); 715 g_return_if_fail(gaim_dbus_connection);
682 #else 716 #else
683 if (gaim_dbus_connection == NULL) 717 if (gaim_dbus_connection == NULL)
684 return; 718 return;
685 #endif 719 #endif
686 720
687 721
688 /* The test below is a hack that prevents our "dbus-method-called" 722 /*
689 signal from being propagated to dbus. What we really need is a 723 * The test below is a hack that prevents our "dbus-method-called"
690 flag for each signal that states whether this signal is to be 724 * signal from being propagated to dbus. What we really need is a
691 dbus-propagated or not. */ 725 * flag for each signal that states whether this signal is to be
692 if (!strcmp(name, "dbus-method-called")) 726 * dbus-propagated or not.
693 return; 727 */
694 728 if (!strcmp(name, "dbus-method-called"))
695 newname = gaim_dbus_convert_signal_name(name); 729 return;
696 signal = dbus_message_new_signal(DBUS_PATH_GAIM, DBUS_INTERFACE_GAIM, newname); 730
697 dbus_message_iter_init_append(signal, &iter); 731 newname = gaim_dbus_convert_signal_name(name);
698 732 signal = dbus_message_new_signal(DBUS_PATH_GAIM, DBUS_INTERFACE_GAIM, newname);
699 gaim_dbus_message_append_gaim_values(&iter, num_values, values, vargs); 733 dbus_message_iter_init_append(signal, &iter);
700 734
701 dbus_connection_send(gaim_dbus_connection, signal, NULL); 735 gaim_dbus_message_append_gaim_values(&iter, num_values, values, vargs);
702 736
703 g_free(newname); 737 dbus_connection_send(gaim_dbus_connection, signal, NULL);
704 dbus_message_unref(signal); 738
739 g_free(newname);
740 dbus_message_unref(signal);
705 } 741 }
706 742
707 const char * 743 const char *
708 gaim_dbus_get_init_error(void) 744 gaim_dbus_get_init_error(void)
709 { 745 {
711 } 747 }
712 748
713 void * 749 void *
714 gaim_dbus_get_handle(void) 750 gaim_dbus_get_handle(void)
715 { 751 {
716 static int handle; 752 static int handle;
717 753
718 return &handle; 754 return &handle;
719 } 755 }
720 756
721 void 757 void
722 gaim_dbus_init(void) 758 gaim_dbus_init(void)
723 { 759 {
724 gaim_dbus_init_ids(); 760 gaim_dbus_init_ids();
725 761
726 g_free(init_error); 762 g_free(init_error);
727 init_error = NULL; 763 init_error = NULL;
728 gaim_dbus_dispatch_init(); 764 gaim_dbus_dispatch_init();
729 if (init_error != NULL) 765 if (init_error != NULL)