2
* @file geis_dbus_subscription.c
3
* @brief Implementation of the GEIS DBus subscription transport.
7
* Copyright 2011 Canonical Ltd.
9
* This library is free software; you can redistribute it and/or modify it under
10
* the terms of the GNU Lesser General Public License as published by the Free
11
* Software Foundation; either version 3 of the License, or (at your option) any
14
* This library is distributed in the hope that it will be useful, but WITHOUT
15
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
19
* You should have received a copy of the GNU General Public License
20
* along with this program. If not, see <http://www.gnu.org/licenses/>.
22
#include "geis_config.h"
23
#include "geis_dbus_subscription.h"
25
#include "geis_dbus.h"
26
#include "geis_dbus_attr.h"
27
#include "geis_filter_term.h"
28
#include "geis_logging.h"
29
#include "geis_subscription.h"
34
* A filter term is marshalled as a (facility, operation, value) tuple.
35
* That would be a (ii(sv)) in DBusspeak.
37
#define GEIS_DBUS_TYPE_SIGNATURE_TERM \
38
DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
39
DBUS_TYPE_INT32_AS_STRING \
40
DBUS_TYPE_INT32_AS_STRING \
41
GEIS_DBUS_TYPE_SIGNATURE_ATTR \
42
DBUS_STRUCT_END_CHAR_AS_STRING
45
* A term list is an array of terms, as in a(ii(sv)).
47
#define GEIS_DBUS_TYPE_SIGNATURE_TERM_LIST \
48
DBUS_TYPE_ARRAY_AS_STRING \
49
GEIS_DBUS_TYPE_SIGNATURE_TERM
52
* A filter is a named array of filter terms.
53
* That's a {sa(ii(sv))} in the DBus tongue.
55
#define GEIS_DBUS_TYPE_SIGNATURE_FILTER \
56
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING \
57
DBUS_TYPE_STRING_AS_STRING \
58
GEIS_DBUS_TYPE_SIGNATURE_TERM_LIST \
59
DBUS_DICT_ENTRY_END_CHAR_AS_STRING
63
* Adds filter terms to a DBus message.
65
* @param[in] filter The filter for which terms will be marshalled.
66
* @param[in] filter_iter A DBus message output iterator.
69
_geis_dbus_marshall_subscription_filter_terms(GeisFilter filter,
70
DBusMessageIter *filter_iter)
72
DBusMessageIter term_list_iter;
73
dbus_message_iter_open_container(filter_iter,
75
GEIS_DBUS_TYPE_SIGNATURE_TERM,
77
for (GeisSize i = 0; i < geis_filter_term_count(filter); ++i)
79
GeisFilterTerm term = geis_filter_term(filter, i);
80
dbus_int32_t facility = geis_filter_term_facility(term);
81
dbus_int32_t operation = geis_filter_term_operation(term);
82
GeisAttr attr = geis_filter_term_attr(term);
84
DBusMessageIter term_iter;
85
dbus_message_iter_open_container(&term_list_iter,
89
dbus_message_iter_append_basic(&term_iter, DBUS_TYPE_INT32, &facility);
90
dbus_message_iter_append_basic(&term_iter, DBUS_TYPE_INT32, &operation);
91
geis_dbus_attr_marshall(attr, &term_iter);
92
dbus_message_iter_close_container(&term_list_iter, &term_iter);
94
dbus_message_iter_close_container(filter_iter, &term_list_iter);
99
* Squeezes the filters on a subscription into the DBus wire protocol.
101
* @param[in] sub A %GeisSubscription
102
* @param[in] msg_iter The open output iterator for a DBus message.
104
* The filters are marshalled as an array of DBus dict entries.
107
_geis_dbus_marshall_subscription_filters(GeisSubscription subscription,
108
DBusMessageIter *msg_iter)
110
DBusMessageIter filter_list_iter;
112
dbus_message_iter_open_container(msg_iter,
114
GEIS_DBUS_TYPE_SIGNATURE_FILTER,
117
for (GeisFilterIterator it = geis_subscription_filter_begin(subscription);
118
it != geis_subscription_filter_end(subscription);
119
it = geis_subscription_filter_next(subscription, it))
121
const char *filter_name = geis_filter_name(*it);
123
DBusMessageIter filter_iter;
124
dbus_message_iter_open_container(&filter_list_iter,
125
DBUS_TYPE_DICT_ENTRY,
128
dbus_message_iter_append_basic(&filter_iter, DBUS_TYPE_STRING, &filter_name);
129
_geis_dbus_marshall_subscription_filter_terms(*it, &filter_iter);
130
dbus_message_iter_close_container(&filter_list_iter, &filter_iter);
132
dbus_message_iter_close_container(msg_iter, &filter_list_iter);
137
_geis_dbus_unmarshall_filter_terms(GeisFilter filter,
138
DBusMessageIter *filter_iter)
140
DBusMessageIter term_list_iter;
141
dbus_message_iter_recurse(filter_iter, &term_list_iter);
142
for (int dtype = dbus_message_iter_get_arg_type(&term_list_iter);
143
dtype != DBUS_TYPE_INVALID;
144
dbus_message_iter_next(&term_list_iter),
145
dtype = dbus_message_iter_get_arg_type(&term_list_iter))
147
int ttype = dbus_message_iter_get_arg_type(&term_list_iter);
148
if (ttype != DBUS_TYPE_STRUCT)
150
geis_error("malformed GeisSubscription term");
154
DBusMessageIter term_iter;
155
dbus_message_iter_recurse(&term_list_iter, &term_iter);
157
dbus_int32_t facility;
158
dbus_message_iter_get_basic(&term_iter, &facility);
159
dbus_message_iter_next(&term_iter);
161
dbus_int32_t operation;
162
dbus_message_iter_get_basic(&term_iter, &operation);
163
dbus_message_iter_next(&term_iter);
165
GeisAttr attr = geis_dbus_attr_unmarshall(&term_iter);
166
GeisFilterTerm term = geis_filter_term_new(facility, operation, attr);
167
geis_filter_add_term_internal(filter, term);
176
* Unmarshalls a filter from a DBus message.
178
* @param[in] geis A GEIS instance.
179
* @param[in] filter_iter A DBus message iterator pointing to the filter.
182
_geis_dbus_unmarshall_filter(Geis geis, DBusMessageIter *filter_iter)
184
GeisFilter filter = NULL;
186
int ftype = dbus_message_iter_get_arg_type(filter_iter);
187
if (ftype != DBUS_TYPE_DICT_ENTRY)
189
geis_error("malformed GeisSubscription filter");
193
DBusMessageIter dict_iter;
194
dbus_message_iter_recurse(filter_iter, &dict_iter);
196
ftype = dbus_message_iter_get_arg_type(&dict_iter);
197
if (ftype != DBUS_TYPE_STRING)
199
geis_error("malformed GeisSubscription filter");
202
GeisString filter_name;
203
dbus_message_iter_get_basic(&dict_iter, &filter_name);
204
dbus_message_iter_next(&dict_iter);
206
filter = geis_filter_new(geis, filter_name);
208
ftype = dbus_message_iter_get_arg_type(&dict_iter);
209
if (ftype != DBUS_TYPE_ARRAY)
211
geis_error("malformed GeisSubscription filter");
214
_geis_dbus_unmarshall_filter_terms(filter, &dict_iter);
222
* Unmarshalls a list of filters from a DBus message.
224
* @param[in] geis A GEIS instance.
225
* @param[in] subscription_iter A DBus message iterator for the subscription.
226
* @param[in] subscription A GEIS subsccription.
228
* This function unmarshalls filters from a GEIS DBus subscription message and
229
* adds them to a existing GEIS subscription.
232
_geis_dbus_unmarshall_subscription_filters(Geis geis,
233
DBusMessageIter *subscription_iter,
234
GeisSubscription subscription)
236
DBusMessageIter filter_list_iter;
237
dbus_message_iter_recurse(subscription_iter, &filter_list_iter);
238
for (int dtype = dbus_message_iter_get_arg_type(&filter_list_iter);
239
dtype != DBUS_TYPE_INVALID;
240
dbus_message_iter_next(&filter_list_iter),
241
dtype = dbus_message_iter_get_arg_type(&filter_list_iter))
243
GeisFilter filter = _geis_dbus_unmarshall_filter(geis, &filter_list_iter);
246
geis_subscription_add_filter(subscription, filter);
253
* Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_CREATE method call.
256
geis_dbus_message_is_subscription_create_call(DBusMessage *message)
258
return dbus_message_is_method_call(message,
259
GEIS_DBUS_SERVICE_INTERFACE,
260
GEIS_DBUS_SUBSCRIPTION_CREATE);
265
* Creates a GEIS_DBUS_SUBSCRIPTION_CREATE method call message.
268
geis_dbus_subscription_create_call_message(GeisSubscription subscription)
270
DBusMessage *message = NULL;
271
GeisString sub_name = "dummy";
272
dbus_int32_t sub_id = -1;
273
dbus_uint32_t sub_flags = 0;
274
DBusMessageIter iter;
276
message = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE,
277
GEIS_DBUS_SERVICE_PATH,
278
GEIS_DBUS_SERVICE_INTERFACE,
279
GEIS_DBUS_SUBSCRIPTION_CREATE);
283
sub_name = geis_subscription_name(subscription);
284
sub_id = geis_subscription_id(subscription);
285
sub_flags = geis_subscription_flags(subscription);
287
dbus_message_iter_init_append(message, &iter);
289
dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &sub_name);
290
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &sub_id);
291
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &sub_flags);
292
_geis_dbus_marshall_subscription_filters(subscription, &iter);
299
* Creates a %GeisSubscription from a method call message.
302
geis_dbus_subscription_from_create_call_message(Geis geis, DBusMessage *message)
304
DBusMessageIter message_iter;
305
dbus_message_iter_init(message, &message_iter);
307
GeisString client_sub_name;
308
dbus_message_iter_get_basic(&message_iter, &client_sub_name);
309
dbus_message_iter_next(&message_iter);
311
dbus_int32_t client_sub_id;
312
dbus_message_iter_get_basic(&message_iter, &client_sub_id);
313
dbus_message_iter_next(&message_iter);
315
dbus_uint32_t client_sub_flags;
316
dbus_message_iter_get_basic(&message_iter, &client_sub_flags);
317
dbus_message_iter_next(&message_iter);
319
GeisSubscription subscription = NULL;
320
subscription = geis_subscription_new(geis, client_sub_name, client_sub_flags);
323
geis_error("error creating proxy subscription");
326
intptr_t fudge = client_sub_id;
327
geis_subscription_set_pdata(subscription, (GeisPointer)fudge);
329
int dtype = dbus_message_iter_get_arg_type(&message_iter);
330
if (dtype != DBUS_TYPE_ARRAY)
332
geis_error("malformed GeisSubscription message"
333
" (expected type %c, received type %c)",
334
DBUS_TYPE_ARRAY, dtype);
338
_geis_dbus_unmarshall_subscription_filters(geis, &message_iter, subscription);
346
* Creates a GEIS_DBUS_SUBSCRIPTION_CREATE method return message.
349
geis_dbus_subscription_create_return_message(DBusMessage *message,
350
GeisSubscription subscription)
352
DBusMessage *reply = dbus_message_new_method_return(message);
353
intptr_t fudge = (intptr_t)geis_subscription_pdata(subscription);
354
dbus_int32_t client_sub_id = fudge;
355
dbus_int32_t server_sub_id = geis_subscription_id(subscription);
356
dbus_message_append_args(reply,
357
DBUS_TYPE_INT32, &client_sub_id,
358
DBUS_TYPE_INT32, &server_sub_id,
366
* Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_ACTIVATE message.
369
geis_dbus_message_is_subscription_activate_call(DBusMessage *message)
371
return dbus_message_is_method_call(message,
372
GEIS_DBUS_SERVICE_INTERFACE,
373
GEIS_DBUS_SUBSCRIPTION_ACTIVATE);
378
* Creates a GEIS_DBUS_SUBSCRIPTION_ACTIVATE method call message.
381
geis_dbus_subscription_activate_call_message(GeisSubscription subscription)
383
DBusMessage *message = NULL;
384
DBusMessageIter iter;
386
message = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE,
387
GEIS_DBUS_SERVICE_PATH,
388
GEIS_DBUS_SERVICE_INTERFACE,
389
GEIS_DBUS_SUBSCRIPTION_ACTIVATE);
390
dbus_message_iter_init_append(message, &iter);
392
dbus_int32_t subscription_id = geis_subscription_id(subscription);
393
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &subscription_id);
394
_geis_dbus_marshall_subscription_filters(subscription, &iter);
400
* Creates a GEIS_DBUS_SUBSCRIPTION_ACTIVATE method return message.
403
geis_dbus_subscription_activate_return_message(DBusMessage *message,
404
GeisSubscription subscription)
406
DBusMessage *reply = NULL;
407
reply = dbus_message_new_method_return(message);
408
dbus_int32_t subscription_id = -1;
412
subscription_id = geis_subscription_id(subscription);
414
dbus_message_append_args(reply,
415
DBUS_TYPE_INT32, &subscription_id,
422
* Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_DEACTIVATE message.
425
geis_dbus_message_is_subscription_deactivate_call(DBusMessage *message)
427
return dbus_message_is_method_call(message,
428
GEIS_DBUS_SERVICE_INTERFACE,
429
GEIS_DBUS_SUBSCRIPTION_DEACTIVATE);
434
* Creates a GEIS_DBUS_SUBSCRIPTION_DEACTIVATE method call message.
437
geis_dbus_subscription_deactivate_call_message(GeisSubscription subscription GEIS_UNUSED)
439
DBusMessage *message = NULL;
440
message = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE,
441
GEIS_DBUS_SERVICE_PATH,
442
GEIS_DBUS_SERVICE_INTERFACE,
443
GEIS_DBUS_SUBSCRIPTION_DEACTIVATE);
451
geis_dbus_subscription_deactivate_return_message(DBusMessage *message,
452
GeisSubscription subscription)
454
DBusMessage *reply = NULL;
455
reply = dbus_message_new_method_return(message);
456
dbus_int32_t subscription_id = geis_subscription_id(subscription);
457
dbus_message_append_args(reply,
458
DBUS_TYPE_INT32, &subscription_id,
465
* Indicates if a DBus message is a GEIS_DBUS_SUBSCRIPTION_DESTROY message.
468
geis_dbus_message_is_subscription_destroy_call(DBusMessage *message)
470
return dbus_message_is_method_call(message,
471
GEIS_DBUS_SERVICE_INTERFACE,
472
GEIS_DBUS_SUBSCRIPTION_DESTROY);
477
* Creates a GEIS_DBUS_SUBSCRIPTION_DESTROY method call message.
480
geis_dbus_subscription_destroy_call_message(GeisSubscription subscription)
482
DBusMessage *message = NULL;
483
message = dbus_message_new_method_call(GEIS_DBUS_SERVICE_INTERFACE,
484
GEIS_DBUS_SERVICE_PATH,
485
GEIS_DBUS_SERVICE_INTERFACE,
486
GEIS_DBUS_SUBSCRIPTION_DESTROY);
488
dbus_int32_t server_sub_id = (intptr_t)geis_subscription_pdata(subscription);
489
dbus_message_append_args(message,
490
DBUS_TYPE_INT32, &server_sub_id,
498
* Creates a GEIS_DBUS_SUBSCRIPTION_DESTROY method return message.
501
geis_dbus_subscription_destroy_return_message(DBusMessage *message)
503
return dbus_message_new_method_return(message);