diff --git a/clients/c/cosmopolite-int.h b/clients/c/cosmopolite-int.h index 2da8957..d4f9bba 100644 --- a/clients/c/cosmopolite-int.h +++ b/clients/c/cosmopolite-int.h @@ -10,6 +10,11 @@ struct cosmo_command { promise *promise; }; +struct cosmo_get_profile { + struct cosmo_get_profile *next; + promise *promise; +}; + struct cosmo { char client_id[COSMO_UUID_SIZE]; char instance_id[COSMO_UUID_SIZE]; @@ -21,6 +26,7 @@ struct cosmo { pthread_cond_t cond; bool shutdown; json_t *profile; + struct cosmo_get_profile *get_profile_head; json_t *generation; struct cosmo_command *command_queue_head; struct cosmo_command *command_queue_tail; diff --git a/clients/c/cosmopolite.c b/clients/c/cosmopolite.c index 96ee9ae..d011834 100644 --- a/clients/c/cosmopolite.c +++ b/clients/c/cosmopolite.c @@ -452,6 +452,15 @@ static struct cosmo_command *cosmo_send_rpc(cosmo *instance, struct cosmo_comman json_decref(instance->profile); json_incref(profile); instance->profile = profile; + struct cosmo_get_profile *get_profile_iter = instance->get_profile_head; + while (get_profile_iter) { + struct cosmo_get_profile *next = get_profile_iter->next; + json_incref(instance->profile); + promise_succeed(get_profile_iter->promise, instance->profile, (promise_cleanup)json_decref); + free(get_profile_iter); + get_profile_iter = next; + } + instance->get_profile_head = NULL; } assert(!clock_gettime(CLOCK_MONOTONIC, &instance->last_success)); @@ -575,8 +584,29 @@ void cosmo_uuid(char *uuid) { uuid_unparse_lower(uu, uuid); } -const char *cosmo_current_profile(cosmo *instance) { - return json_string_value(instance->profile); +void cosmo_get_profile(cosmo *instance, promise *promise_obj) { + assert(!pthread_mutex_lock(&instance->lock)); + if (json_is_string(instance->profile)) { + json_t *profile = instance->profile; + json_incref(profile); + assert(!pthread_mutex_unlock(&instance->lock)); + promise_succeed(promise_obj, instance->profile, (promise_cleanup)json_decref); + return; + } + struct cosmo_get_profile *entry = malloc(sizeof(*entry)); + assert(entry); + entry->next = instance->get_profile_head; + entry->promise = promise_obj; + instance->get_profile_head = entry; + assert(!pthread_mutex_unlock(&instance->lock)); +} + +json_t *cosmo_current_profile(cosmo *instance) { + assert(!pthread_mutex_lock(&instance->lock)); + json_t *profile = instance->profile; + json_incref(profile); + assert(!pthread_mutex_unlock(&instance->lock)); + return profile; } json_t *cosmo_subject(const char *name, const char *readable_only_by, const char *writeable_only_by) { @@ -722,6 +752,7 @@ cosmo *cosmo_create(const char *base_url, const char *client_id, const cosmo_cal instance->shutdown = false; instance->profile = json_null(); + instance->get_profile_head = NULL; instance->generation = json_null(); instance->command_queue_head = instance->command_queue_tail = NULL; instance->ack = json_array(); @@ -758,6 +789,13 @@ void cosmo_shutdown(cosmo *instance) { json_decref(instance->ack); json_decref(instance->subscriptions); json_decref(instance->profile); + struct cosmo_get_profile *get_profile_iter = instance->get_profile_head; + while (get_profile_iter) { + struct cosmo_get_profile *next = get_profile_iter->next; + promise_fail(get_profile_iter->promise, NULL, NULL); + free(get_profile_iter); + get_profile_iter = next; + } json_decref(instance->generation); curl_easy_cleanup(instance->curl); diff --git a/clients/c/cosmopolite.h b/clients/c/cosmopolite.h index 8c23120..977df19 100644 --- a/clients/c/cosmopolite.h +++ b/clients/c/cosmopolite.h @@ -31,7 +31,8 @@ void cosmo_uuid(char *uuid); cosmo *cosmo_create(const char *base_url, const char *client_id, const cosmo_callbacks *callbacks, const cosmo_options *options, void *passthrough); void cosmo_shutdown(cosmo *instance); -const char *cosmo_current_profile(cosmo *instance); +void cosmo_get_profile(cosmo *instance, promise *promise_obj); +json_t *cosmo_current_profile(cosmo *instance); json_t *cosmo_subject(const char *name, const char *readable_only_by, const char *writeable_only_by); void cosmo_subscribe(cosmo *instance, json_t *subjects, const json_int_t messages, const json_int_t last_id, promise *promise_obj); diff --git a/clients/c/test.c b/clients/c/test.c index 15063d5..762ef4b 100644 --- a/clients/c/test.c +++ b/clients/c/test.c @@ -450,6 +450,47 @@ static bool test_message_ordering(test_state *state) { return true; } +static bool test_subscribe_acl(test_state *state) { + cosmo *client = create_client(state); + promise *promise_obj = promise_create(NULL, NULL, NULL); + cosmo_get_profile(client, promise_obj); + json_t *bad_profile; + assert(promise_wait(promise_obj, (void **) &bad_profile)); + json_incref(bad_profile); + promise_destroy(promise_obj); + cosmo_shutdown(client); + + client = create_client(state); + + promise_obj = promise_create(NULL, NULL, NULL); + cosmo_get_profile(client, promise_obj); + json_t *good_profile; + assert(promise_wait(promise_obj, (void **) &good_profile)); + json_incref(good_profile); + promise_destroy(promise_obj); + + json_t *good_subject = random_subject(json_string_value(good_profile), NULL); + promise_obj = promise_create(NULL, NULL, NULL); + cosmo_subscribe(client, good_subject, -1, 0, promise_obj); + assert(promise_wait(promise_obj, NULL)); + promise_destroy(promise_obj); + + json_t *bad_subject = random_subject(json_string_value(bad_profile), NULL); + promise_obj = promise_create(NULL, NULL, NULL); + cosmo_subscribe(client, bad_subject, -1, 0, promise_obj); + assert(!promise_wait(promise_obj, NULL)); + promise_destroy(promise_obj); + + json_decref(good_subject); + json_decref(bad_subject); + json_decref(good_profile); + json_decref(bad_profile); + + cosmo_shutdown(client); + + return true; +} + int main(int argc, char *argv[]) { RUN_TEST(test_create_shutdown); RUN_TEST(test_client_id_change_fires); @@ -465,6 +506,7 @@ int main(int argc, char *argv[]) { RUN_TEST(test_subscribe_barrier); RUN_TEST(test_resubscribe); RUN_TEST(test_message_ordering); + RUN_TEST(test_subscribe_acl); return 0; }