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