static bool _CatalogRemoveToken(_Catalog *catalog, const char *token, bool notify) { _Subscription *subs = _SubscriptionAcquire(catalog, token); if (!subs) return false; if (notify && catalog->cancel_function) { catalog->cancel_function(catalog->sh, subs->message, catalog->cancel_function_ctx); } _CatalogLock(catalog); int i; // Remove subscription from key sublists for (i = 0; i < subs->keys->len; i++) { const char *key = g_ptr_array_index(subs->keys, i); _SubList *sub_list = g_hash_table_lookup(catalog->subscription_lists, key); _SubListRemove(sub_list, token); if (_SubListLen(sub_list) == 0) { g_hash_table_remove(catalog->subscription_lists, key); } } // Remove subscrition from client subscription list const char *client_name = LSMessageGetSender(subs->message); _SubList *client_sub_list = g_hash_table_lookup(catalog->client_subscriptions, client_name); _SubListRemove(client_sub_list, token); if (_SubListLen(client_sub_list) == 0) { g_hash_table_remove(catalog->client_subscriptions, client_name); } _CatalogUnlock(catalog); _SubscriptionRemove(catalog, subs, token); _SubscriptionRelease(catalog, subs); return true; }
/** * @brief Returns a string that uniquely represents this message. * * @param message * * @retval */ const char * LSMessageGetUniqueToken(LSMessage *message) { if (!message) return NULL; if (message->uniqueTokenAllocated) return message->uniqueTokenAllocated; const char *sender = LSMessageGetSender(message); LSMessageToken token = LSMessageGetToken(message); message->uniqueTokenAllocated = g_strdup_printf("%s.%ld", sender, token); return message->uniqueTokenAllocated; }
bool _CatalogHandleCancel(_Catalog *catalog, LSMessage *cancelMsg, LSError *lserror) { JSchemaInfo schemaInfo; jschema_info_init(&schemaInfo, jschema_all(), NULL, NULL); const char *sender; int token; jvalue_ref tokenObj = NULL; const char *payload = LSMessageGetPayload(cancelMsg); jvalue_ref object = jdom_parse(j_cstr_to_buffer(payload), DOMOPT_NOOPT, &schemaInfo); if (jis_null(object)) { _LSErrorSet(lserror, MSGID_LS_INVALID_JSON, -EINVAL, "Invalid json"); goto error; } sender = LSMessageGetSender(cancelMsg); if (!jobject_get_exists(object, J_CSTR_TO_BUF("token"), &tokenObj) || tokenObj == NULL || !jis_number(tokenObj)) { _LSErrorSet(lserror, MSGID_LS_INVALID_JSON, -EINVAL, "Invalid json"); goto error; } (void)jnumber_get_i32(tokenObj, &token);/* TODO: handle appropriately */ char *uniqueToken = g_strdup_printf("%s.%d", sender, token); _CatalogCallCancelNotifications(catalog, uniqueToken); _CatalogRemoveToken(catalog, uniqueToken, true); g_free(uniqueToken); j_release(&object); return true; error: j_release(&object); return false; }
bool _LSPrivateGetSubscriptions(LSHandle* sh, LSMessage *message, void *ctx) { LSError lserror; LSErrorInit(&lserror); const char *sender = LSMessageGetSenderServiceName(message); if (!sender || strcmp(sender, MONITOR_NAME) != 0) { g_critical("WARNING: subscription debug method not called by monitor;" " ignoring (service name: %s, unique_name: %s)", sender, LSMessageGetSender(message)); return true; } struct json_object *ret_obj = NULL; bool json_ret = _LSSubscriptionGetJson(sh, &ret_obj, &lserror); if (!json_ret) { LSErrorPrint(&lserror, stderr); LSErrorFree(&lserror); return true; } bool reply_ret = LSMessageReply(sh, message, json_object_to_json_string(ret_obj), &lserror); if (!reply_ret) { g_critical("%s: sending subscription info failed", __FUNCTION__); LSErrorPrint(&lserror, stderr); LSErrorFree(&lserror); } json_object_put(ret_obj); return true; }
bool _LSPrivateGetMallinfo(LSHandle* sh, LSMessage *message, void *ctx) { LSError lserror; LSErrorInit(&lserror); struct json_object *ret_obj = NULL; struct json_object *true_obj = NULL; struct json_object *mallinfo_obj = NULL; struct json_object *allocator_name_obj = NULL; struct json_object *slot_a_obj = NULL; struct json_object *slot_d_obj = NULL; struct json_object *slot_e_obj = NULL; struct json_object *slot_f_obj = NULL; struct json_object *slot_h_obj = NULL; struct json_object *slot_i_obj = NULL; struct json_object *slot_j_obj = NULL; const char *sender = LSMessageGetSenderServiceName(message); if (!sender || strcmp(sender, MONITOR_NAME) != 0) { g_critical("WARNING: mallinfo debug method not called by monitor;" " ignoring (service name: %s, unique_name: %s)", sender, LSMessageGetSender(message)); return true; } ret_obj = json_object_new_object(); if (JSON_ERROR(ret_obj)) goto error; true_obj = json_object_new_boolean(true); if (JSON_ERROR(true_obj)) goto error; mallinfo_obj = json_object_new_object(); if (JSON_ERROR(mallinfo_obj)) goto error; /* returnValue: true, * mallinfo: {key: int,...} */ typedef struct mallinfo (*mallinfo_t)(); static mallinfo_t mallinfo_p = NULL; if (mallinfo_p == NULL) { mallinfo_p = (mallinfo_t)dlsym(RTLD_DEFAULT, "mallinfo"); if (mallinfo_p == NULL) mallinfo_p = (mallinfo_t)-1; } struct mallinfo mi; if (mallinfo_p != (mallinfo_t)-1) { mi = mallinfo_p(); } else { memset(&mi, '\0', sizeof(mi)); } allocator_name_obj = json_object_new_string("ptmalloc"); if (JSON_ERROR(allocator_name_obj)) goto error; slot_a_obj = json_object_new_int(mi.arena); if (JSON_ERROR(slot_a_obj)) goto error; slot_d_obj = json_object_new_int(mi.hblks); if (JSON_ERROR(slot_d_obj)) goto error; slot_e_obj = json_object_new_int(mi.hblkhd); if (JSON_ERROR(slot_e_obj)) goto error; slot_f_obj = json_object_new_int(mi.usmblks); if (JSON_ERROR(slot_f_obj)) goto error; slot_h_obj = json_object_new_int(mi.uordblks); if (JSON_ERROR(slot_h_obj)) goto error; slot_i_obj = json_object_new_int(mi.fordblks); if (JSON_ERROR(slot_i_obj)) goto error; slot_j_obj = json_object_new_int(mi.keepcost); if (JSON_ERROR(slot_j_obj)) goto error; json_object_object_add(mallinfo_obj, "allocator", allocator_name_obj); json_object_object_add(mallinfo_obj, "sbrk_bytes", slot_a_obj); json_object_object_add(mallinfo_obj, "mmap_count", slot_d_obj); json_object_object_add(mallinfo_obj, "mmap_bytes", slot_e_obj); json_object_object_add(mallinfo_obj, "max_malloc_bytes", slot_f_obj); json_object_object_add(mallinfo_obj, "malloc_bytes", slot_h_obj); json_object_object_add(mallinfo_obj, "slack_bytes", slot_i_obj); json_object_object_add(mallinfo_obj, "trimmable_slack_bytes", slot_j_obj); json_object_object_add(ret_obj, "returnValue", true_obj); json_object_object_add(ret_obj, "mallinfo", mallinfo_obj); bool reply_ret = LSMessageReply(sh, message, json_object_to_json_string(ret_obj), &lserror); if (!reply_ret) { g_critical("%s: sending malloc info failed", __FUNCTION__); LSErrorPrint(&lserror, stderr); LSErrorFree(&lserror); } json_object_put(ret_obj); return true; error: if (!JSON_ERROR(ret_obj)) json_object_put(ret_obj); if (!JSON_ERROR(true_obj)) json_object_put(true_obj); if (!JSON_ERROR(mallinfo_obj)) json_object_put(mallinfo_obj); if (!JSON_ERROR(allocator_name_obj)) json_object_put(allocator_name_obj); if (!JSON_ERROR(slot_a_obj)) json_object_put(slot_a_obj); if (!JSON_ERROR(slot_d_obj)) json_object_put(slot_d_obj); if (!JSON_ERROR(slot_e_obj)) json_object_put(slot_e_obj); if (!JSON_ERROR(slot_f_obj)) json_object_put(slot_f_obj); if (!JSON_ERROR(slot_h_obj)) json_object_put(slot_h_obj); if (!JSON_ERROR(slot_i_obj)) json_object_put(slot_i_obj); if (!JSON_ERROR(slot_j_obj)) json_object_put(slot_j_obj); return true; }
bool _LSSubscriptionGetJson(LSHandle *sh, jvalue_ref *ret_obj, LSError *lserror) { _Catalog *catalog = sh->catalog; const char *key = NULL; _SubList *sub_list = NULL; GHashTableIter iter; jvalue_ref true_obj = NULL; jvalue_ref array = NULL; jvalue_ref cur_obj = NULL; jvalue_ref sub_array = NULL; jvalue_ref key_name = NULL; jvalue_ref message_obj = NULL; jvalue_ref sub_array_item = NULL; jvalue_ref unique_name_obj = NULL; jvalue_ref service_name_obj = NULL; *ret_obj = jobject_create(); if (*ret_obj == NULL) goto error; true_obj = jboolean_create(true); if (true_obj == NULL) goto error; array = jarray_create(NULL); if (array == NULL) goto error; /* returnValue: true, * subscriptions: [ * { key: key_name, subscribers: [{unique_name: , service_name: }, ...] }, * ... * ] */ _CatalogLock(catalog); g_hash_table_iter_init(&iter, catalog->subscription_lists); while (g_hash_table_iter_next(&iter, (gpointer)&key, (gpointer)&sub_list)) { cur_obj = jobject_create(); if (cur_obj == NULL) goto error; sub_array = jarray_create(NULL); if (sub_array == NULL) goto error; key_name = jstring_create_copy(j_cstr_to_buffer(key)); if (key_name == NULL) goto error; /* iterate over SubList */ int i = 0; const char *token = NULL; const int len = _SubListLen(sub_list); for (i = 0; i < len; i++) { token = _SubListGet(sub_list, i); if (token) { _Subscription *sub = g_hash_table_lookup(catalog->token_map, token); if (!sub) continue; LSMessage *msg = sub->message; const char *unique_name = LSMessageGetSender(msg); const char *service_name = LSMessageGetSenderServiceName(msg); const char *message_body = LSMessageGetPayload(msg); /* create subscribers item and add to sub_array */ sub_array_item = jobject_create(); if (sub_array_item == NULL) goto error; unique_name_obj = unique_name ? jstring_create_copy(j_cstr_to_buffer(unique_name)) : jstring_empty(); if (unique_name_obj == NULL) goto error; service_name_obj = service_name ? jstring_create_copy(j_cstr_to_buffer(service_name)) : jstring_empty(); if (service_name_obj == NULL) goto error; message_obj = message_body ? jstring_create_copy(j_cstr_to_buffer(message_body)) : jstring_empty(); if (message_obj == NULL) goto error; jobject_put(sub_array_item, J_CSTR_TO_JVAL("unique_name"), unique_name_obj); jobject_put(sub_array_item, J_CSTR_TO_JVAL("service_name"), service_name_obj); jobject_put(sub_array_item, J_CSTR_TO_JVAL("subscription_message"), message_obj); jarray_append(sub_array, sub_array_item); sub_array_item = NULL; unique_name_obj = NULL; service_name_obj = NULL; message_obj = NULL; } } jobject_put(cur_obj, J_CSTR_TO_JVAL("key"), key_name); jobject_put(cur_obj, J_CSTR_TO_JVAL("subscribers"), sub_array); jarray_append(array, cur_obj); key_name = NULL; cur_obj = NULL; sub_array = NULL; } jobject_put(*ret_obj, J_CSTR_TO_JVAL("returnValue"), true_obj); jobject_put(*ret_obj, J_CSTR_TO_JVAL("subscriptions"), array); _CatalogUnlock(catalog); return true; error: _CatalogUnlock(catalog); j_release(ret_obj); j_release(&true_obj); j_release(&array); j_release(&cur_obj); j_release(&sub_array); j_release(&key_name); j_release(&sub_array_item); j_release(&unique_name_obj); j_release(&service_name_obj); return false; }
static bool _CatalogAdd(_Catalog *catalog, const char *key, LSMessage *message, LSError *lserror) { bool retVal = false; const char *token = LSMessageGetUniqueToken(message); if (!token) { _LSErrorSet(lserror, MSGID_LS_TOKEN_ERR, -1, "Could not get unique token"); return false; } _CatalogLock(catalog); _SubList *list = g_hash_table_lookup(catalog->subscription_lists, key); if (!list) { list = _SubListNew(); g_hash_table_replace(catalog->subscription_lists, g_strdup(key), list); } const char* client_name = LSMessageGetSender(message); if (!client_name) { _LSErrorSet(lserror, MSGID_LS_UNAME_ERR, -1, "Could not get service unique name"); return false; } _SubList *client_list = g_hash_table_lookup(catalog->client_subscriptions, client_name); if (!client_list) { client_list = _SubListNew(); g_hash_table_replace(catalog->client_subscriptions, g_strdup(client_name), client_list); } _Subscription *subs = g_hash_table_lookup(catalog->token_map, token); if (!subs) { subs = _SubscriptionNew(catalog->sh, message); if (subs) { g_hash_table_replace(catalog->token_map, g_strdup(token), subs); } else { goto cleanup; } } LS_ASSERT(subs->message == message); if (!_SubListContains(list, token)) { _SubListAdd(list, g_strdup(token)); } if (!_SubListContains(client_list, token)) { _SubListAdd(client_list, g_strdup(token)); } if (!g_char_ptr_array_contains(subs->keys, key)) { g_ptr_array_add(subs->keys, g_strdup(key)); } retVal = true; cleanup: _CatalogUnlock(catalog); return retVal; }