00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <microfeed-subscriber/microfeedsubscriber.h>
00020 #include <microfeed-common/microfeedmisc.h>
00021 #include <microfeed-common/microfeedconfiguration.h>
00022 #include <microfeed-common/microfeedprotocol.h>
00023
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <time.h>
00028 #include <sys/types.h>
00029 #include <dirent.h>
00030
00031
00032
00033 struct _MicrofeedSubscriber {
00034 char* identifier;
00035 DBusConnection* connection;
00036 char* object_path;
00037 MicrofeedConfiguration* configuration;
00038 unsigned int max_retries;
00039
00040 MicrofeedStore* publishers_by_identifier;
00041 MicrofeedStore* providers_by_bus_name;
00042 MicrofeedStore* providers_by_unique_connection_name;
00043 };
00044
00045 typedef struct {
00046 MicrofeedSubscriber* subscriber;
00047 char* bus_name;
00048 char* unique_connection_name;
00049 MicrofeedStore* publishers_by_object_path;
00050 } Provider;
00051
00052 typedef struct {
00053 unsigned int reference_count;
00054 Provider* provider;
00055 char* identifier;
00056 char* object_path;
00057 time_t last_activity;
00058 MicrofeedStore* feeds;
00059 } Publisher;
00060
00061 typedef struct {
00062 unsigned int reference_count;
00063 Publisher* publisher;
00064 char* uri;
00065 char* name;
00066 MicrofeedSubscriberCallbacks callbacks;
00067 void* user_data;
00068 } Feed;
00069
00070 typedef struct {
00071 const char* name;
00072 void (*callback)(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message);
00073 } SignalCallback;
00074
00075 typedef struct {
00076 Publisher* publisher;
00077 char* uri;
00078 char* uid;
00079 DBusMessage* message;
00080 unsigned int retry_counter;
00081 MicrofeedSubscriberErrorCallback callback;
00082 void* user_data;
00083 } MethodReturnData;
00084
00085 static Provider* provider_new(MicrofeedSubscriber* subscriber, const char* bus_name);
00086 static void provider_free(Provider* provider);
00087 static const char* provider_get_bus_name(Provider* provider);
00088 static const char* provider_get_unique_connection_name(Provider* provider);
00089 static void provider_set_unique_connection_name(Provider* provider, const char* unique_connection_name);
00090
00091 static Publisher* publisher_new(Provider* provider, const char* identifier);
00092 static void publisher_free(Publisher* publisher);
00093 Publisher* publisher_ref(Publisher* publisher);
00094 void publisher_unref(Publisher* publisher);
00095 static const char* publisher_get_identifier(Publisher* publisher);
00096 static const char* publisher_get_object_path(Publisher* publisher);
00097
00098 static Feed* feed_new(Publisher* publisher, const char* uri, MicrofeedSubscriberCallbacks* callbacks, void* user_data);
00099 static void feed_free(Feed* feed);
00100 static const char* feed_get_uri(Feed* feed);
00101
00102 static void call_publisher_method(Publisher* publisher, const char* uri, const char* uid, DBusMessage* message, MicrofeedSubscriberErrorCallback callback, void* user_data);
00103 static MicrofeedItem* parse_item_from_message(DBusMessageIter* iter);
00104 static int parse_item_signal(Publisher* publisher, DBusMessage* message, Feed** feed_return, MicrofeedItem** item_return);
00105 static int parse_feed_signal(Publisher* publisher, DBusMessage* message, Feed** feed_return);
00106 static Publisher* get_publisher(MicrofeedSubscriber* subscriber, const char* publisher_identifier, const char* uri, const char* uid, MicrofeedSubscriberErrorCallback callback, void* user_data);
00107 static Feed* get_feed(MicrofeedSubscriber* subscriber, const char* publisher_identifier, const char* uri, const char* uid, MicrofeedSubscriberErrorCallback callback, void* user_data);
00108 static void object_unregister(DBusConnection* connection, void* user_data);
00109 static DBusHandlerResult object_message(DBusConnection* connection, DBusMessage* message, void* user_data);
00110
00111 static void signal_feed_update_started(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message);
00112 static void signal_feed_update_ended(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message);
00113 static void signal_feed_republishing_started(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message);
00114 static void signal_feed_republishing_ended(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message);
00115 static void signal_item_data(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message);
00116 static void signal_item_added(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message);
00117 static void signal_item_changed(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message);
00118 static void signal_item_republished(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message);
00119 static void signal_item_removed(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message);
00120 static void signal_item_status_changed(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message);
00121
00122 static SignalCallback signal_callbacks[] = {
00123 { MICROFEED_SIGNAL_NAME_FEED_UPDATE_STARTED, signal_feed_update_started },
00124 { MICROFEED_SIGNAL_NAME_FEED_UPDATE_ENDED, signal_feed_update_ended },
00125 { MICROFEED_SIGNAL_NAME_FEED_REPUBLISHING_STARTED, signal_feed_republishing_started },
00126 { MICROFEED_SIGNAL_NAME_FEED_REPUBLISHING_ENDED, signal_feed_republishing_ended },
00127 { MICROFEED_SIGNAL_NAME_ITEM_DATA, signal_item_data },
00128 { MICROFEED_SIGNAL_NAME_ITEM_ADDED, signal_item_added },
00129 { MICROFEED_SIGNAL_NAME_ITEM_CHANGED, signal_item_changed },
00130 { MICROFEED_SIGNAL_NAME_ITEM_REPUBLISHED, signal_item_republished },
00131 { MICROFEED_SIGNAL_NAME_ITEM_REMOVED, signal_item_removed },
00132 { MICROFEED_SIGNAL_NAME_ITEM_STATUS_CHANGED, signal_item_status_changed },
00133 { NULL, NULL }
00134 };
00135
00136 static DBusObjectPathVTable object_vtable = {
00137 object_unregister,
00138 object_message
00139 };
00140
00141 MicrofeedSubscriber* microfeed_subscriber_new(const char* identifier, const char* object_path, DBusConnection* connection) {
00142 MicrofeedSubscriber* subscriber;
00143
00144 subscriber = microfeed_memory_allocate(MicrofeedSubscriber);
00145 subscriber->identifier = strdup(identifier);
00146 subscriber->connection = connection;
00147 subscriber->object_path = strdup(object_path);
00148 subscriber->configuration = microfeed_configuration_new();
00149 subscriber->max_retries = 3;
00150
00151 subscriber->publishers_by_identifier = microfeed_store_new_sorted((MicrofeedStoreCompareKeysFunction)strcmp,
00152 (MicrofeedStoreGetKeyFunction)publisher_get_identifier);
00153 subscriber->providers_by_bus_name = microfeed_store_new_sorted((MicrofeedStoreCompareKeysFunction)strcmp,
00154 (MicrofeedStoreGetKeyFunction)provider_get_bus_name);
00155 subscriber->providers_by_unique_connection_name = microfeed_store_new_sorted((MicrofeedStoreCompareKeysFunction)strcmp,
00156 (MicrofeedStoreGetKeyFunction)provider_get_unique_connection_name);
00157
00158 if (!dbus_connection_register_object_path(subscriber->connection, subscriber->object_path, &object_vtable, subscriber)) {
00159
00160 return NULL;
00161 }
00162 if (!dbus_connection_add_filter(subscriber->connection, object_message, subscriber, NULL)) {
00163
00164 return NULL;
00165 }
00166
00167 return subscriber;
00168 }
00169
00173 void microfeed_subscriber_free(MicrofeedSubscriber* subscriber) {
00174
00175 }
00176
00177 const char* microfeed_subscriber_get_identifier(MicrofeedSubscriber* subscriber) {
00178
00179 return subscriber->identifier;
00180 }
00181
00182 int microfeed_subscriber_add_item(MicrofeedSubscriber* subscriber, const char* publisher_identifier, const char* uri, MicrofeedItem* item, MicrofeedSubscriberErrorCallback callback, void* user_data) {
00183 int retvalue = 0;
00184 Publisher* publisher;
00185 DBusMessage* message;
00186 DBusMessageIter iter;
00187 const char* uid;
00188 MicrofeedItemIterator* iterator;
00189 const char* key;
00190 const char* value;
00191
00192 if ((publisher = get_publisher(subscriber, publisher_identifier, uri, microfeed_item_get_uid(item), callback, user_data))) {
00193 message = dbus_message_new_method_call(publisher->provider->bus_name, publisher->object_path, MICROFEED_DBUS_INTERFACE_PUBLISHER, MICROFEED_METHOD_NAME_ADD_ITEM);
00194 dbus_message_iter_init_append(message, &iter);
00195 uid = microfeed_item_get_uid(item);
00196 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &uri);
00197 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &uid);
00198 for (iterator = microfeed_item_iterate_properties(item, NULL);
00199 microfeed_item_iterator_get(iterator, &key, &value);
00200 microfeed_item_iterator_next(iterator)) {
00201 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key);
00202 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &value);
00203 }
00204 microfeed_item_iterator_free(iterator);
00205 call_publisher_method(publisher, uri, microfeed_item_get_uid(item), message, callback, user_data);
00206 dbus_message_unref(message);
00207 retvalue = 1;
00208 }
00209
00210 return retvalue;
00211 }
00212
00213 int microfeed_subscriber_modify_item(MicrofeedSubscriber*subscriber, const char* publisher_identifier, const char* uri, MicrofeedItem* item, MicrofeedSubscriberErrorCallback callback, void* user_data) {
00214 int retvalue = 0;
00215 Publisher* publisher;
00216 DBusMessage* message;
00217 DBusMessageIter iter;
00218 const char* uid;
00219 MicrofeedItemIterator* iterator;
00220 const char* key;
00221 const char* value;
00222
00223 if ((publisher = get_publisher(subscriber, publisher_identifier, uri, microfeed_item_get_uid(item), callback, user_data))) {
00224 message = dbus_message_new_method_call(publisher->provider->bus_name, publisher->object_path, MICROFEED_DBUS_INTERFACE_PUBLISHER, MICROFEED_METHOD_NAME_MODIFY_ITEM);
00225 dbus_message_iter_init_append(message, &iter);
00226 uid = microfeed_item_get_uid(item);
00227 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &uri);
00228 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &uid);
00229 for (iterator = microfeed_item_iterate_properties(item, NULL);
00230 microfeed_item_iterator_get(iterator, &key, &value);
00231 microfeed_item_iterator_next(iterator)) {
00232 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key);
00233 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &value);
00234 }
00235 microfeed_item_iterator_free(iterator);
00236 call_publisher_method(publisher, uri, microfeed_item_get_uid(item), message, callback, user_data);
00237 dbus_message_unref(message);
00238 retvalue = 1;
00239 }
00240
00241 return retvalue;
00242 }
00243
00244 int microfeed_subscriber_remove_item(MicrofeedSubscriber* subscriber, const char* publisher_identifier, const char* uri, const char* uid, MicrofeedSubscriberReplyCallback callback, void* user_data) {
00245 int retvalue = 0;
00246 Publisher* publisher;
00247 DBusMessage* message;
00248
00249 if ((publisher = get_publisher(subscriber, publisher_identifier, uri, uid, callback, user_data))) {
00250 message = dbus_message_new_method_call(publisher->provider->bus_name, publisher->object_path, MICROFEED_DBUS_INTERFACE_PUBLISHER, MICROFEED_METHOD_NAME_REMOVE_ITEM);
00251 dbus_message_append_args(message, DBUS_TYPE_STRING, &uri, DBUS_TYPE_STRING, &uid, DBUS_TYPE_INVALID);
00252 call_publisher_method(publisher, uri, uid, message, callback, user_data);
00253 dbus_message_unref(message);
00254 retvalue = 1;
00255 }
00256
00257 return retvalue;
00258
00259 }
00260
00261 int microfeed_subscriber_subscribe_feed(MicrofeedSubscriber* subscriber, const char* publisher_identifier, const char* uri, MicrofeedSubscriberCallbacks* callbacks, MicrofeedSubscriberErrorCallback callback, void* user_data) {
00262 int retvalue = 0;
00263 Publisher* publisher;
00264 Feed* feed;
00265 DBusMessage* message;
00266
00267 if ((publisher = get_publisher(subscriber, publisher_identifier, uri, NULL, callback, user_data))) {
00268 if ((feed = microfeed_store_get(publisher->feeds, uri, Feed))) {
00269 if (callback) {
00270 callback(subscriber, publisher_identifier, uri, NULL, MICROFEED_ERROR_FEED_ALREADY_SUBSCRIBED, "Subscribed a feed that is already subscribed.", user_data);
00271 }
00272 } else {
00273 feed = feed_new(publisher, uri, callbacks, user_data);
00274
00275 message = dbus_message_new_method_call(feed->publisher->provider->bus_name, feed->publisher->object_path, MICROFEED_DBUS_INTERFACE_PUBLISHER, MICROFEED_METHOD_NAME_SUBSCRIBE_FEED);
00276 dbus_message_append_args(message, DBUS_TYPE_STRING, &feed->uri, DBUS_TYPE_INVALID);
00277 call_publisher_method(publisher, uri, NULL, message, callback, user_data);
00278 dbus_message_unref(message);
00279 retvalue = 1;
00280 }
00281 }
00282
00283 return retvalue;
00284 }
00285
00286 int microfeed_subscriber_unsubscribe_feed(MicrofeedSubscriber* subscriber, const char* publisher_identifier, const char* uri, MicrofeedSubscriberErrorCallback callback, void* user_data) {
00287 int retvalue = 0;
00288 Feed* feed;
00289 DBusMessage* message;
00290 Publisher* publisher;
00291
00292 if ((feed = get_feed(subscriber, publisher_identifier, uri, NULL, callback, user_data))) {
00293 message = dbus_message_new_method_call(feed->publisher->provider->bus_name, feed->publisher->object_path, MICROFEED_DBUS_INTERFACE_PUBLISHER, MICROFEED_METHOD_NAME_UNSUBSCRIBE_FEED);
00294 dbus_message_append_args(message, DBUS_TYPE_STRING, &feed->uri, DBUS_TYPE_INVALID);
00295 call_publisher_method(feed->publisher, feed->uri, NULL, message, callback, user_data);
00296 dbus_message_unref(message);
00297 retvalue = 1;
00298
00299 publisher = feed->publisher;
00300 feed_free(feed);
00301 if (microfeed_store_get_size(publisher->feeds) == 0) {
00302 publisher_unref(publisher);
00303 }
00304 }
00305
00306 return retvalue;
00307 }
00308
00309 int microfeed_subscriber_update_feed(MicrofeedSubscriber* subscriber, const char* publisher_identifier, const char* uri, MicrofeedSubscriberErrorCallback callback, void* user_data) {
00310 int retvalue = 0;
00311 Feed* feed;
00312 DBusMessage* message;
00313
00314 if ((feed = get_feed(subscriber, publisher_identifier, uri, NULL, callback, user_data))) {
00315 message = dbus_message_new_method_call(feed->publisher->provider->bus_name, feed->publisher->object_path, MICROFEED_DBUS_INTERFACE_PUBLISHER, MICROFEED_METHOD_NAME_UPDATE_FEED);
00316 dbus_message_append_args(message, DBUS_TYPE_STRING, &uri, DBUS_TYPE_INVALID);
00317 call_publisher_method(feed->publisher, feed->uri, NULL, message, callback, user_data);
00318 dbus_message_unref(message);
00319 retvalue = 1;
00320 }
00321
00322 return retvalue;
00323 }
00324
00325 int microfeed_subscriber_republish_items(MicrofeedSubscriber* subscriber, const char* publisher_identifier, const char* uri, const char* start_uid, const char* end_uid, unsigned int max_count, MicrofeedSubscriberErrorCallback callback, void* user_data) {
00326 int retvalue = 0;
00327 Feed* feed;
00328 DBusMessage* message;
00329 const char* start_uid_dbus;
00330 const char* end_uid_dbus;
00331 dbus_uint16_t max_count_dbus;
00332
00333 if ((feed = get_feed(subscriber, publisher_identifier, uri, start_uid, callback, user_data))) {
00334 message = dbus_message_new_method_call(feed->publisher->provider->bus_name, feed->publisher->object_path, MICROFEED_DBUS_INTERFACE_PUBLISHER, MICROFEED_METHOD_NAME_REPUBLISH_ITEMS);
00335 start_uid_dbus = (start_uid ? start_uid : "");
00336 end_uid_dbus = (end_uid ? end_uid : "");
00337 max_count_dbus = max_count;
00338 dbus_message_append_args(message, DBUS_TYPE_STRING, &uri, DBUS_TYPE_STRING, &start_uid_dbus, DBUS_TYPE_STRING, &end_uid_dbus, DBUS_TYPE_UINT16, &max_count_dbus, DBUS_TYPE_INVALID);
00339 call_publisher_method(feed->publisher, feed->uri, start_uid, message, callback, user_data);
00340 dbus_message_unref(message);
00341 retvalue = 1;
00342 }
00343
00344 return retvalue;
00345 }
00346
00347 int microfeed_subscriber_send_item_data(MicrofeedSubscriber* subscriber, const char* publisher_identifier, const char* uri, const char* uid, MicrofeedSubscriberErrorCallback callback, void* user_data) {
00348 int retvalue = 0;
00349 Publisher* publisher;
00350 DBusMessage* message;
00351
00352 if ((publisher = get_publisher(subscriber, publisher_identifier, NULL, uid, callback, user_data))) {
00353 message = dbus_message_new_method_call(publisher->provider->bus_name, publisher->object_path, MICROFEED_DBUS_INTERFACE_PUBLISHER, MICROFEED_METHOD_NAME_SEND_ITEM_DATA);
00354 dbus_message_append_args(message, DBUS_TYPE_STRING, &uri, DBUS_TYPE_STRING, &uid, DBUS_TYPE_INVALID);
00355 call_publisher_method(publisher, NULL, uid, message, callback, user_data);
00356 dbus_message_unref(message);
00357 retvalue = 1;
00358 }
00359
00360 return retvalue;
00361 }
00362
00363 int microfeed_subscriber_create_publisher(MicrofeedSubscriber* subscriber, const char* publisher_identifier, MicrofeedSubscriberErrorCallback callback, void* user_data) {
00364 int retvalue = 0;
00365 Publisher* publisher;
00366 DBusMessage* message;
00367
00368 microfeed_configuration_invalidate(subscriber->configuration);
00369 if (microfeed_configuration_get_publisher_directory(subscriber->configuration, publisher_identifier)) {
00370 if (callback) {
00371 callback(subscriber, publisher_identifier, NULL, NULL, MICROFEED_ERROR_PUBLISHER_ALREADY_EXISTS, "Trying to create a publisher that already exists.", user_data);
00372 }
00373 } else if ((publisher = get_publisher(subscriber, publisher_identifier, NULL, NULL, callback, user_data))) {
00374 message = dbus_message_new_method_call(publisher->provider->bus_name, publisher->object_path, MICROFEED_DBUS_INTERFACE_PUBLISHER, MICROFEED_METHOD_NAME_CREATE_PUBLISHER);
00375 call_publisher_method(publisher, NULL, NULL, message, callback, user_data);
00376 dbus_message_unref(message);
00377 retvalue = 1;
00378 }
00379
00380 return retvalue;
00381 }
00382
00383 int microfeed_subscriber_destroy_publisher(MicrofeedSubscriber* subscriber, const char* publisher_identifier, MicrofeedSubscriberErrorCallback callback, void* user_data) {
00384 int retvalue = 0;
00385 Publisher* publisher;
00386 DBusMessage* message;
00387
00388 if ((publisher = get_publisher(subscriber, publisher_identifier, NULL, NULL, callback, user_data))) {
00389 message = dbus_message_new_method_call(publisher->provider->bus_name, publisher->object_path, MICROFEED_DBUS_INTERFACE_PUBLISHER, MICROFEED_METHOD_NAME_DESTROY_PUBLISHER);
00390 call_publisher_method(publisher, NULL, NULL, message, callback, user_data);
00391 dbus_message_unref(message);
00392 retvalue = 1;
00393 }
00394
00395 return retvalue;
00396 }
00397
00398 int microfeed_subscriber_mark_item(MicrofeedSubscriber* subscriber, const char* publisher_identifier, const char* uri, const char* uid, MicrofeedSubscriberErrorCallback callback, void* user_data) {
00399 int retvalue = 0;
00400 Publisher* publisher;
00401 DBusMessage* message;
00402
00403 if ((publisher = get_publisher(subscriber, publisher_identifier, NULL, NULL, callback, user_data))) {
00404 message = dbus_message_new_method_call(publisher->provider->bus_name, publisher->object_path, MICROFEED_DBUS_INTERFACE_PUBLISHER, MICROFEED_METHOD_NAME_MARK_ITEM);
00405 dbus_message_append_args(message, DBUS_TYPE_STRING, &uri, DBUS_TYPE_STRING, &uid, DBUS_TYPE_INVALID);
00406 call_publisher_method(publisher, uri, uid, message, callback, user_data);
00407 dbus_message_unref(message);
00408 retvalue = 1;
00409 }
00410
00411 return retvalue;
00412 }
00413
00414 int microfeed_subscriber_unmark_item(MicrofeedSubscriber* subscriber, const char* publisher_identifier, const char* uri, const char* uid, MicrofeedSubscriberErrorCallback callback, void* user_data) {
00415 int retvalue = 0;
00416 Publisher* publisher;
00417 DBusMessage* message;
00418
00419 if ((publisher = get_publisher(subscriber, publisher_identifier, NULL, NULL, callback, user_data))) {
00420 message = dbus_message_new_method_call(publisher->provider->bus_name, publisher->object_path, MICROFEED_DBUS_INTERFACE_PUBLISHER, MICROFEED_METHOD_NAME_UNMARK_ITEM);
00421 dbus_message_append_args(message, DBUS_TYPE_STRING, &uri, DBUS_TYPE_STRING, &uid, DBUS_TYPE_INVALID);
00422 call_publisher_method(publisher, uri, uid, message, callback, user_data);
00423 dbus_message_unref(message);
00424 retvalue = 1;
00425 }
00426
00427 return retvalue;
00428 }
00429
00430 int microfeed_subscriber_read_items(MicrofeedSubscriber* subscriber, const char* publisher_identifier, const char* uri, const char* start_uid, const char* end_uid, MicrofeedSubscriberReplyCallback callback, void* user_data) {
00431 int retvalue = 0;
00432 Feed* feed;
00433 DBusMessage* message;
00434 const char* start_uid_dbus;
00435 const char* end_uid_dbus;
00436
00437 if ((feed = get_feed(subscriber, publisher_identifier, uri, start_uid, callback, user_data))) {
00438 message = dbus_message_new_method_call(feed->publisher->provider->bus_name, feed->publisher->object_path, MICROFEED_DBUS_INTERFACE_PUBLISHER, MICROFEED_METHOD_NAME_READ_ITEMS);
00439 start_uid_dbus = (start_uid ? start_uid : "");
00440 end_uid_dbus = (end_uid ? end_uid : "");
00441 dbus_message_append_args(message, DBUS_TYPE_STRING, &uri, DBUS_TYPE_STRING, &start_uid_dbus, DBUS_TYPE_STRING, &end_uid_dbus, DBUS_TYPE_INVALID);
00442 call_publisher_method(feed->publisher, feed->uri, start_uid, message, callback, user_data);
00443 dbus_message_unref(message);
00444 retvalue = 1;
00445 }
00446
00447 return retvalue;
00448 }
00449
00450
00451 MicrofeedConfiguration* microfeed_subscriber_get_configuration(MicrofeedSubscriber* subscriber) {
00452
00453 return subscriber->configuration;
00454 }
00455
00456 int microfeed_subscriber_handle_configured_subscriptions(MicrofeedSubscriber* subscriber, MicrofeedSubscriberConfiguredSubscribeCallback configured_subscribe, MicrofeedSubscriberConfiguredUnsubscribeCallback configured_unsubscribe, void* user_data) {
00457 int retvalue = 0;
00458 const char** subscriptions;
00459 const char** s;
00460 MicrofeedStoreIterator* publishers_iterator;
00461 Publisher* publisher;
00462 MicrofeedStoreIterator* feeds_iterator;
00463 Feed* feed;
00464
00465 microfeed_configuration_invalidate(subscriber->configuration);
00466 if ((subscriptions = microfeed_configuration_get_subscriptions(subscriber->configuration, subscriber->identifier))) {
00467 retvalue = 1;
00468
00469
00470 for (s = subscriptions; *s; s++) {
00471 if (!microfeed_store_get(subscriber->publishers_by_identifier, *s, Publisher)) {
00472 configured_subscribe(subscriber, *s, user_data);
00473 }
00474 }
00475
00476
00477 for (publishers_iterator = microfeed_store_iterate(subscriber->publishers_by_identifier, NULL);
00478 (publisher = microfeed_store_iterator_get(publishers_iterator, Publisher));
00479 microfeed_store_iterator_next(publishers_iterator)) {
00480 for (s = subscriptions; *s; s++) {
00481 if (!strcmp(publisher->identifier, *s)) {
00482 break;
00483 }
00484 }
00485 if (!*s) {
00486 for (feeds_iterator = microfeed_store_iterate(publisher->feeds, NULL);
00487 (feed = microfeed_store_iterator_get(feeds_iterator, Feed));
00488 microfeed_store_iterator_next(feeds_iterator)) {
00489 configured_unsubscribe(subscriber, publisher->identifier, feed->uri, user_data);
00490 }
00491 }
00492 }
00493 }
00494
00495 return retvalue;
00496 }
00497
00498 static Provider* provider_new(MicrofeedSubscriber* subscriber, const char* bus_name) {
00499 Provider* provider;
00500
00501 provider = microfeed_memory_allocate(Provider);
00502 provider->subscriber = subscriber;
00503 provider->bus_name = strdup(bus_name);
00504 provider->publishers_by_object_path = microfeed_store_new_sorted((MicrofeedStoreCompareKeysFunction)strcmp,
00505 (MicrofeedStoreGetKeyFunction)publisher_get_object_path);
00506
00507 microfeed_store_insert(subscriber->providers_by_bus_name, provider);
00508
00509 return provider;
00510 }
00511
00512 static void provider_free(Provider* provider) {
00513 microfeed_store_remove(provider->subscriber->providers_by_bus_name, provider);
00514 provider_set_unique_connection_name(provider, NULL);
00515
00516 free(provider->bus_name);
00517 free(provider->unique_connection_name);
00518 microfeed_store_free(provider->publishers_by_object_path);
00519 provider->subscriber = NULL;
00520 provider->bus_name = NULL;
00521 provider->unique_connection_name = NULL;
00522 provider->publishers_by_object_path = NULL;
00523 microfeed_memory_free(provider);
00524 }
00525
00526 static const char* provider_get_bus_name(Provider* provider) {
00527
00528 return provider->bus_name;
00529 }
00530
00531 static const char* provider_get_unique_connection_name(Provider* provider) {
00532
00533 return (provider->unique_connection_name ? provider->unique_connection_name : "");
00534 }
00535
00536 static void provider_set_unique_connection_name(Provider* provider, const char* unique_connection_name) {
00537 char buffer[1024];
00538
00539 if (unique_connection_name) {
00540 if (provider->unique_connection_name) {
00541 provider_set_unique_connection_name(provider, NULL);
00542 }
00543 provider->unique_connection_name = strdup(unique_connection_name);
00544 microfeed_store_insert(provider->subscriber->providers_by_unique_connection_name, provider);
00545
00546 snprintf(buffer, 1024, "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0='%s'", provider->unique_connection_name);
00547 dbus_bus_add_match(provider->subscriber->connection, buffer, NULL);
00548 snprintf(buffer, 1024, "type='signal',sender='%s',interface='%s'", provider->unique_connection_name, MICROFEED_DBUS_INTERFACE_PUBLISHER);
00549 dbus_bus_add_match(provider->subscriber->connection, buffer, NULL);
00550 snprintf(buffer, 1024, "type='signal',sender='%s',interface='%s',destination='%s'", provider->unique_connection_name, MICROFEED_DBUS_INTERFACE_PUBLISHER_TO_DESTINATION, dbus_bus_get_unique_name(provider->subscriber->connection));
00551 dbus_bus_add_match(provider->subscriber->connection, buffer, NULL);
00552 snprintf(buffer, 1024, "type='signal',sender='%s',interface='%s'", provider->unique_connection_name, MICROFEED_DBUS_INTERFACE_ERROR);
00553 dbus_bus_add_match(provider->subscriber->connection, buffer, NULL);
00554 snprintf(buffer, 1024, "type='signal',sender='%s',interface='%s',destination ='%s'", provider->unique_connection_name, MICROFEED_DBUS_INTERFACE_ERROR_TO_DESTINATION, dbus_bus_get_unique_name(provider->subscriber->connection));
00555 dbus_bus_add_match(provider->subscriber->connection, buffer, NULL);
00556 } else if (provider->unique_connection_name) {
00557 snprintf(buffer, 1024, "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0='%s'", provider->unique_connection_name);
00558 dbus_bus_remove_match(provider->subscriber->connection, buffer, NULL);
00559 snprintf(buffer, 1024, "type='signal',sender='%s',interface='%s'", provider->unique_connection_name, MICROFEED_DBUS_INTERFACE_PUBLISHER);
00560 dbus_bus_remove_match(provider->subscriber->connection, buffer, NULL);
00561 snprintf(buffer, 1024, "type='signal',sender='%s',interface='%s',destination='%s'", provider->unique_connection_name, MICROFEED_DBUS_INTERFACE_PUBLISHER_TO_DESTINATION, dbus_bus_get_unique_name(provider->subscriber->connection));
00562 dbus_bus_remove_match(provider->subscriber->connection, buffer, NULL);
00563 snprintf(buffer, 1024, "type='signal',sender='%s',interface='%s'", provider->unique_connection_name, MICROFEED_DBUS_INTERFACE_ERROR);
00564 dbus_bus_remove_match(provider->subscriber->connection, buffer, NULL);
00565 snprintf(buffer, 1024, "type='signal',sender='%s',interface='%s',destination='%s'", provider->unique_connection_name, MICROFEED_DBUS_INTERFACE_ERROR_TO_DESTINATION, dbus_bus_get_unique_name(provider->subscriber->connection));
00566
00567 microfeed_store_remove(provider->subscriber->providers_by_unique_connection_name, provider);
00568 free(provider->unique_connection_name);
00569 provider->unique_connection_name = NULL;
00570 }
00571 }
00572
00573 static Publisher* publisher_new(Provider* provider, const char* identifier) {
00574 Publisher* publisher = NULL;
00575 char* separator;
00576
00577 publisher = microfeed_memory_allocate(Publisher);
00578 publisher->reference_count = 1;
00579 publisher->identifier = strdup(identifier);
00580 if ((separator = strchr(publisher->identifier, MICROFEED_PUBLISHER_IDENTIFIER_SEPARATOR_CHAR))) {
00581 *separator = 0;
00582 publisher->object_path = microfeed_util_string_concatenate(MICROFEED_DBUS_OBJECT_PATH_PREFIX_PUBLISHER, publisher->identifier, NULL);
00583 *separator = MICROFEED_PUBLISHER_IDENTIFIER_SEPARATOR_CHAR;
00584 } else {
00585 publisher->object_path = strdup(identifier);
00586 }
00587 publisher->feeds = microfeed_store_new_sorted((MicrofeedStoreCompareKeysFunction)strcmp,
00588 (MicrofeedStoreGetKeyFunction)feed_get_uri);
00589 publisher->provider = provider;
00590
00591 microfeed_store_insert(provider->publishers_by_object_path, publisher);
00592 microfeed_store_insert(provider->subscriber->publishers_by_identifier, publisher);
00593
00594 return publisher;
00595 }
00596
00597 static void publisher_free(Publisher* publisher) {
00598 microfeed_store_remove(publisher->provider->subscriber->publishers_by_identifier, publisher);
00599 microfeed_store_remove(publisher->provider->publishers_by_object_path, publisher);
00600 if (microfeed_store_get_size(publisher->provider->publishers_by_object_path) == 0) {
00601 provider_free(publisher->provider);
00602 }
00603
00604 free(publisher->identifier);
00605 free(publisher->object_path);
00606 publisher->provider = NULL;
00607 publisher->identifier = NULL;
00608 publisher->object_path = NULL;
00609 microfeed_store_free(publisher->feeds);
00610 microfeed_memory_free(publisher);
00611 }
00612
00613 Publisher* publisher_ref(Publisher* publisher) {
00614 publisher->reference_count++;
00615
00616 return publisher;
00617 }
00618
00619 void publisher_unref(Publisher* publisher) {
00620 publisher->reference_count--;
00621 if (publisher->reference_count == 0) {
00622 publisher_free(publisher);
00623 }
00624 }
00625
00626 static const char* publisher_get_identifier(Publisher* publisher) {
00627
00628 return publisher->identifier;
00629 }
00630
00631 static const char* publisher_get_object_path(Publisher* publisher) {
00632
00633 return publisher->object_path;
00634 }
00635
00636 static Feed* feed_new(Publisher* publisher, const char* uri, MicrofeedSubscriberCallbacks* callbacks, void* user_data) {
00637 Feed* feed;
00638
00639 feed = microfeed_memory_allocate(Feed);
00640 feed->reference_count = 1;
00641 feed->publisher = publisher;
00642 feed->uri = strdup(uri);
00643 feed->callbacks = *callbacks;
00644 feed->user_data = user_data;
00645
00646 microfeed_store_insert(publisher->feeds, feed);
00647
00648 return feed;
00649 }
00650
00651 static void feed_free(Feed* feed) {
00652 microfeed_store_remove(feed->publisher->feeds, feed);
00653
00654 free(feed->uri);
00655 free(feed->name);
00656 feed->publisher = NULL;
00657 feed->uri = NULL;
00658 feed->name = NULL;
00659 feed->user_data = NULL;
00660 microfeed_memory_free(feed);
00661 }
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677 static const char* feed_get_uri(Feed* feed) {
00678
00679 return feed->uri;
00680 }
00681
00682 static void signal_feed_update_started(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message) {
00683 Feed* feed;
00684
00685 if (parse_feed_signal(publisher, message, &feed) && feed->callbacks.feed_update_started) {
00686 feed->callbacks.feed_update_started(subscriber, publisher->identifier, feed->uri, feed->user_data);
00687 }
00688 }
00689
00690 static void signal_feed_update_ended(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message) {
00691 Feed* feed;
00692
00693 if (parse_feed_signal(publisher, message, &feed) && feed->callbacks.feed_update_ended) {
00694 feed->callbacks.feed_update_ended(subscriber, publisher->identifier, feed->uri, feed->user_data);
00695 }
00696 }
00697
00698 static void signal_feed_republishing_started(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message) {
00699 Feed* feed;
00700
00701 if (parse_feed_signal(publisher, message, &feed) && feed->callbacks.feed_republishing_started) {
00702 feed->callbacks.feed_republishing_started(subscriber, publisher->identifier, feed->uri, feed->user_data);
00703 }
00704 }
00705
00706 static void signal_feed_republishing_ended(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message) {
00707 Feed* feed;
00708
00709 if (parse_feed_signal(publisher, message, &feed) && feed->callbacks.feed_republishing_ended) {
00710 feed->callbacks.feed_republishing_ended(subscriber, publisher->identifier, feed->uri, feed->user_data);
00711 }
00712 }
00713
00714 static void signal_item_data(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message) {
00715 DBusMessageIter iter;
00716 char* uri;
00717 Feed* feed;
00718 char* uid;
00719 DBusMessageIter subiter;
00720 char* data;
00721 int length;
00722
00723 if (dbus_message_iter_init(message, &iter) && dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) {
00724 dbus_message_iter_get_basic(&iter, &uri);
00725 if ((feed = microfeed_store_get(publisher->feeds, uri, Feed)) && feed->callbacks.item_data_received &&
00726 dbus_message_iter_next(&iter) && dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) {
00727 dbus_message_iter_get_basic(&iter, &uid);
00728 if (dbus_message_iter_next(&iter) && dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY &&
00729 dbus_message_iter_get_element_type(&iter) == DBUS_TYPE_BYTE) {
00730 dbus_message_iter_recurse(&iter, &subiter);
00731 dbus_message_iter_get_fixed_array(&subiter, &data, &length);
00732 feed->callbacks.item_data_received(subscriber, publisher->identifier, uri, uid, data, length, feed->user_data);
00733 }
00734 }
00735 }
00736 }
00737
00738 static void signal_item_added(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message) {
00739 Feed* feed;
00740 MicrofeedItem* item;
00741
00742 if (parse_item_signal(publisher, message, &feed, &item) && feed->callbacks.item_added) {
00743 feed->callbacks.item_added(subscriber, publisher->identifier, feed->uri, item, feed->user_data);
00744 microfeed_item_free(item);
00745 }
00746 }
00747
00748 static void signal_item_changed(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message) {
00749 Feed* feed;
00750 MicrofeedItem* item;
00751
00752 if (parse_item_signal(publisher, message, &feed, &item) && feed->callbacks.item_changed) {
00753 feed->callbacks.item_changed(subscriber, publisher->identifier, feed->uri, item, feed->user_data);
00754 microfeed_item_free(item);
00755 }
00756 }
00757
00758 static void signal_item_republished(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message) {
00759 Feed* feed;
00760 MicrofeedItem* item;
00761
00762 if (parse_item_signal(publisher, message, &feed, &item) && feed->callbacks.item_republished) {
00763 feed->callbacks.item_republished(subscriber, publisher->identifier, feed->uri, item, feed->user_data);
00764 microfeed_item_free(item);
00765 }
00766 }
00767
00768 static void signal_item_removed(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message) {
00769 DBusError error;
00770 char* uri;
00771 char* uid;
00772 Feed* feed;
00773
00774 dbus_error_init(&error);
00775 if (dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &uri, DBUS_TYPE_STRING, &uid, DBUS_TYPE_INVALID) &&
00776 (feed = microfeed_store_get(publisher->feeds, uri, Feed)) && feed->callbacks.item_removed) {
00777 feed->callbacks.item_removed(subscriber, publisher->identifier, uri, uid, feed->user_data);
00778 }
00779 }
00780
00781 static void signal_item_status_changed(MicrofeedSubscriber* subscriber, Publisher* publisher, DBusMessage* message) {
00782 DBusError error;
00783 char* uri;
00784 char* uid;
00785 char status;
00786 Feed* feed;
00787
00788 dbus_error_init(&error);
00789 if (dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &uri, DBUS_TYPE_STRING, &uid, DBUS_TYPE_BYTE, &status, DBUS_TYPE_INVALID) &&
00790 (feed = microfeed_store_get(publisher->feeds, uri, Feed)) && feed->callbacks.item_status_changed) {
00791 feed->callbacks.item_status_changed(subscriber, publisher->identifier, uri, uid, (MicrofeedItemStatus)status, feed->user_data);
00792 }
00793 }
00794
00795 static Publisher* get_publisher(MicrofeedSubscriber* subscriber, const char* publisher_identifier, const char* uri, const char* uid, MicrofeedSubscriberErrorCallback callback, void* user_data) {
00796 Publisher* publisher;
00797 const char* bus_name;
00798 Provider* provider;
00799
00800 if (!(publisher = microfeed_store_get(subscriber->publishers_by_identifier, publisher_identifier, Publisher))) {
00801 if ((bus_name = strchr(publisher_identifier, MICROFEED_PUBLISHER_IDENTIFIER_SEPARATOR_CHAR)) && bus_name[1] != 0) {
00802 bus_name++;
00803 if (!(provider = microfeed_store_get(subscriber->providers_by_bus_name, bus_name, Provider))) {
00804 microfeed_configuration_invalidate(subscriber->configuration);
00805 if (microfeed_configuration_get_provider_name(subscriber->configuration, bus_name)) {
00806 provider = provider_new(subscriber, bus_name);
00807 } else if (callback) {
00808 callback(subscriber, publisher_identifier, uri, uid, MICROFEED_ERROR_NO_SUCH_PROVIDER, "Provider for the publisher does not exist.", user_data);
00809 }
00810 }
00811 if (provider) {
00812 publisher = publisher_new(provider, publisher_identifier);
00813 }
00814 } else if (callback) {
00815 callback(subscriber, publisher_identifier, uri, uid, MICROFEED_ERROR_INVALID_PUBLISHER_IDENTIFIER, "Publisher identifier was invalid.", user_data);
00816 }
00817 }
00818
00819 return publisher;
00820 }
00821
00822 static Feed* get_feed(MicrofeedSubscriber* subscriber, const char* publisher_identifier, const char* uri, const char* uid, MicrofeedSubscriberErrorCallback callback, void* user_data) {
00823 Publisher* publisher;
00824 Feed* feed = NULL;
00825
00826 if (!(publisher = microfeed_store_get(subscriber->publishers_by_identifier, publisher_identifier, Publisher))) {
00827 if (callback) {
00828 callback(subscriber, publisher_identifier, uri, uid, MICROFEED_ERROR_NO_SUCH_PUBLISHER, "Publisher does not exist.", user_data);
00829 }
00830 } else if (!(feed = microfeed_store_get(publisher->feeds, uri, Feed))) {
00831 if (callback) {
00832 callback(subscriber, publisher_identifier, uri, uid, MICROFEED_ERROR_FEED_NOT_SUBSCRIBED, "Trying to access a feed that is not subscribed.", user_data);
00833 }
00834 }
00835
00836 return feed;
00837 }
00838
00839 static MicrofeedItem* parse_item_from_message(DBusMessageIter* iter) {
00840 MicrofeedItem* item = NULL;
00841 char* uid;
00842 dbus_uint64_t timestamp;
00843 unsigned char status;
00844 char* key;
00845 char* value;
00846
00847 if (dbus_message_iter_next(iter) && dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
00848 dbus_message_iter_get_basic(iter, &uid);
00849 if (dbus_message_iter_next(iter) && dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_UINT64) {
00850 dbus_message_iter_get_basic(iter, ×tamp);
00851 if (dbus_message_iter_next(iter) && dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_BYTE) {
00852 dbus_message_iter_get_basic(iter, &status);
00853 item = microfeed_item_new_with_status(uid, (time_t)timestamp, (MicrofeedItemStatus)status);
00854 while (dbus_message_iter_next(iter) && dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
00855 dbus_message_iter_get_basic(iter, &key);
00856 if (dbus_message_iter_next(iter) && dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
00857 dbus_message_iter_get_basic(iter, &value);
00858 microfeed_item_set_property(item, key, value);
00859 }
00860 }
00861 }
00862 } else {
00863 item = microfeed_item_new(uid, 0);
00864 }
00865 }
00866
00867 return item;
00868 }
00869
00870 static int parse_item_signal(Publisher* publisher, DBusMessage* message, Feed** feed_return, MicrofeedItem** item_return) {
00871 int retvalue = 0;
00872 DBusMessageIter iter;
00873 char* uri;
00874 Feed* feed;
00875 MicrofeedItem* item;
00876
00877 if (dbus_message_iter_init(message, &iter) && dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) {
00878 dbus_message_iter_get_basic(&iter, &uri);
00879 if ((feed = microfeed_store_get(publisher->feeds, uri, Feed)) &&
00880 (item = parse_item_from_message(&iter))) {
00881 *feed_return = feed;
00882 *item_return = item;
00883 retvalue = 1;
00884 }
00885 }
00886
00887 return retvalue;
00888 }
00889
00890 static int parse_feed_signal(Publisher* publisher, DBusMessage* message, Feed** feed_return) {
00891 int retvalue = 0;
00892 DBusError error;
00893 const char* uri;
00894 Feed* feed;
00895
00896 dbus_error_init(&error);
00897 if (dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &uri, DBUS_TYPE_INVALID)) {
00898 if ((feed = microfeed_store_get(publisher->feeds, uri, Feed))) {
00899 *feed_return = feed;
00900 retvalue = 1;
00901 }
00902 } else {
00903 dbus_error_free(&error);
00904 }
00905
00906 return retvalue;
00907 }
00908
00909 static void handle_publisher_method_return(DBusPendingCall* pending, void* user_data) {
00910 MethodReturnData* data;
00911 DBusMessage* reply;
00912 DBusError error;
00913 const char* error_name;
00914 const char* error_message;
00915 int retrying = 0;
00916 DBusPendingCall* pending_call;
00917
00918 data = (MethodReturnData*)user_data;
00919 reply = dbus_pending_call_steal_reply(pending);
00920 if (!reply) {
00921 if (data->callback) {
00922 data->callback(data->publisher->provider->subscriber, data->publisher->identifier, data->uri, data->uid, MICROFEED_ERROR_DBUS_MESSAGE_FAILED, "No reply from the publisher.", data->user_data);
00923 }
00924 } else if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
00925 if (data->retry_counter < data->publisher->provider->subscriber->max_retries) {
00926 retrying = 1;
00927 if (data->retry_counter) {
00928
00929 }
00930 data->retry_counter++;
00931
00932 dbus_connection_send_with_reply(data->publisher->provider->subscriber->connection, data->message, &pending_call, -1);
00933 if (pending_call) {
00934 dbus_pending_call_set_notify(pending_call, handle_publisher_method_return, data, NULL);
00935 }
00936 } else if (data->callback) {
00937 if (!(error_name = dbus_message_get_error_name(reply))) {
00938 error_name = MICROFEED_ERROR_UNKNOWN;
00939 }
00940 dbus_error_init(&error);
00941 if (!dbus_message_get_args(reply, &error, DBUS_TYPE_STRING, &error_message, DBUS_TYPE_INVALID)) {
00942 error_message = NULL;
00943 }
00944 data->callback(data->publisher->provider->subscriber, data->publisher->identifier, data->uri, data->uid, error_name, error_message, data->user_data);
00945 }
00946 } else {
00947 if (!data->publisher->provider->unique_connection_name) {
00948 provider_set_unique_connection_name(data->publisher->provider, dbus_message_get_sender(reply));
00949 }
00950 if (data->callback) {
00951 data->callback(data->publisher->provider->subscriber, data->publisher->identifier, data->uri, data->uid, NULL, NULL, data->user_data);
00952 }
00953 }
00954 if (reply) {
00955 dbus_message_unref(reply);
00956 }
00957
00958 if (!retrying) {
00959 dbus_message_unref(data->message);
00960 publisher_unref(data->publisher);
00961 free(data->uri);
00962 free(data->uid);
00963 microfeed_memory_free(data);
00964 }
00965 }
00966
00967 static void call_publisher_method(Publisher* publisher, const char* uri, const char* uid, DBusMessage* message, MicrofeedSubscriberErrorCallback callback, void* user_data) {
00968 DBusPendingCall* pending_call;
00969 MethodReturnData* data;
00970
00971 dbus_connection_send_with_reply(publisher->provider->subscriber->connection, message, &pending_call, -1);
00972 if (pending_call) {
00973 data = microfeed_memory_allocate(MethodReturnData);
00974 data->message = dbus_message_copy(message);
00975 data->publisher = publisher_ref(publisher);
00976 if (uri) {
00977 data->uri = strdup(uri);
00978 } else {
00979 data->uri = NULL;
00980 }
00981 if (uid) {
00982 data->uid = strdup(uid);
00983 } else {
00984 data->uid = NULL;
00985 }
00986 data->callback = callback;
00987 data->user_data = user_data;
00988 dbus_pending_call_set_notify(pending_call, handle_publisher_method_return, data, NULL);
00989 }
00990 }
00991
00992 static void object_unregister(DBusConnection* connection, void* user_data) {
00993 }
00994
00995 static DBusHandlerResult object_message(DBusConnection* connection, DBusMessage* message, void* user_data) {
00996 DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00997 MicrofeedSubscriber* subscriber;
00998 const char* name;
00999 const char* old_owner;
01000 const char* new_owner;
01001 MicrofeedStoreIterator* publisher_iterator;
01002 MicrofeedStoreIterator* feed_iterator;
01003 Feed* feed;
01004 int i;
01005 Provider* provider;
01006 Publisher* publisher;
01007 DBusMessage* reply;
01008 DBusError error;
01009 const char* error_name;
01010 char* error_message;
01011 char* uri;
01012 char* uid;
01013
01014 subscriber = (MicrofeedSubscriber*)user_data;
01015 if (dbus_message_is_signal(message, "org.freedesktop.DBus", "NameOwnerChanged") &&
01016 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old_owner, DBUS_TYPE_STRING, &new_owner, DBUS_TYPE_INVALID) &&
01017 name[0] == ':' && new_owner[0] == 0 && !strcmp(name, old_owner) && (provider = microfeed_store_get(subscriber->providers_by_unique_connection_name, name, Provider))) {
01018 for (publisher_iterator = microfeed_store_iterate(provider->publishers_by_object_path, NULL);
01019 (publisher = microfeed_store_iterator_get(publisher_iterator, Publisher));
01020 microfeed_store_iterator_next(publisher_iterator)) {
01021 for (feed_iterator = microfeed_store_iterate(publisher->feeds, NULL);
01022 (feed = microfeed_store_iterator_get(feed_iterator, Feed));
01023 microfeed_store_iterator_next(feed_iterator)) {
01024 if (feed->callbacks.error_occured) {
01025 feed->callbacks.error_occured(subscriber, publisher->identifier, feed->uri, NULL, MICROFEED_ERROR_PROVIDER_CLOSED_CONNECTION, "Provider closed connection", feed->user_data);
01026 }
01027
01028 }
01029 microfeed_store_iterator_free(feed_iterator);
01030
01031 }
01032 provider_set_unique_connection_name(provider, NULL);
01033 microfeed_store_iterator_free(publisher_iterator);
01034 }
01035
01036 if ((provider = microfeed_store_get(subscriber->providers_by_unique_connection_name, dbus_message_get_sender(message), Provider)) &&
01037 (publisher = microfeed_store_get(provider->publishers_by_object_path, dbus_message_get_path(message), Publisher))) {
01038 publisher->last_activity = time(NULL);
01039 if (dbus_message_is_method_call(message, MICROFEED_DBUS_INTERFACE_SUBSCRIBER, MICROFEED_METHOD_NAME_PING)) {
01040 reply = dbus_message_new_method_return(message);
01041 dbus_connection_send(connection, reply, NULL);
01042 dbus_message_unref(reply);
01043 result = DBUS_HANDLER_RESULT_HANDLED;
01044 } else if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL && (dbus_message_has_interface(message, MICROFEED_DBUS_INTERFACE_ERROR) || dbus_message_has_interface(message, MICROFEED_DBUS_INTERFACE_ERROR_TO_DESTINATION))) {
01045 dbus_error_init(&error);
01046 if ((error_name = dbus_message_get_member(message)) && dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &uri, DBUS_TYPE_STRING, &uid, DBUS_TYPE_STRING, &error_message, DBUS_TYPE_INVALID)) {
01047 if ((feed = microfeed_store_get(publisher->feeds, uri, Feed)) && feed->callbacks.error_occured) {
01048 feed->callbacks.error_occured(subscriber, publisher->identifier, uri, uid, error_name, error_message, feed->user_data);
01049 }
01050 }
01051 } else {
01052 for (i = 0; signal_callbacks[i].name; i++) {
01053 if (dbus_message_is_signal(message, MICROFEED_DBUS_INTERFACE_PUBLISHER, signal_callbacks[i].name) ||
01054 dbus_message_is_signal(message, MICROFEED_DBUS_INTERFACE_PUBLISHER_TO_DESTINATION, signal_callbacks[i].name)) {
01055 signal_callbacks[i].callback(subscriber, publisher, message);
01056 result = DBUS_HANDLER_RESULT_HANDLED;
01057 break;
01058 }
01059 }
01060 }
01061 }
01062
01063 return result;
01064 }
01065