summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2022-03-31 15:40:23 +0200
committerTheJackiMonster <thejackimonster@gmail.com>2022-03-31 15:40:23 +0200
commit5b266a4c6e22ba210086b6d9759fd8aae01abaaf (patch)
tree272f926ef806aee3404b7d23b9945f32904b6b4d
parent2134dfccf8be89fa5e1e595d6ec65a56ac357d78 (diff)
Added account deletion and adjusted automated tests
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
-rw-r--r--include/gnunet_chat_lib.h15
-rw-r--r--src/gnunet_chat_handle.c22
-rw-r--r--src/gnunet_chat_handle.h6
-rw-r--r--src/gnunet_chat_handle_intern.c8
-rw-r--r--src/gnunet_chat_lib.c74
-rw-r--r--src/gnunet_chat_lib_intern.c54
-rw-r--r--tests/test_gnunet_chat.h4
-rw-r--r--tests/test_gnunet_chat_handle.c146
8 files changed, 253 insertions, 76 deletions
diff --git a/include/gnunet_chat_lib.h b/include/gnunet_chat_lib.h
index 9e3fd04..135e82e 100644
--- a/include/gnunet_chat_lib.h
+++ b/include/gnunet_chat_lib.h
@@ -362,6 +362,21 @@ GNUNET_CHAT_account_create (struct GNUNET_CHAT_Handle *handle,
const char* name);
/**
+ * Deletes an existing chat account of a given chat <i>handle</i> under a
+ * unique <i>name</i>.
+ *
+ * If there is no account known to this chat handle under the provided name, the
+ * function will fail and return #GNUNET_NO.
+ *
+ * @param[in,out] handle Chat handle
+ * @param[in] name Account name
+ * @return #GNUNET_OK on success, #GNUNET_NO on failure and otherwise #GNUNET_SYSERR
+ */
+int
+GNUNET_CHAT_account_delete(struct GNUNET_CHAT_Handle *handle,
+ const char* name);
+
+/**
* Iterates through the accounts of a given chat <i>handle</i> with a selected
* callback and custom closure.
*
diff --git a/src/gnunet_chat_handle.c b/src/gnunet_chat_handle.c
index d23741b..cbbbcc7 100644
--- a/src/gnunet_chat_handle.c
+++ b/src/gnunet_chat_handle.c
@@ -40,6 +40,8 @@ handle_create_from_config (const struct GNUNET_CONFIGURATION_Handle* cfg,
on_handle_shutdown, handle
);
+ handle->destruction = NULL;
+
handle->internal_head = NULL;
handle->internal_tail = NULL;
@@ -85,7 +87,6 @@ handle_create_from_config (const struct GNUNET_CONFIGURATION_Handle* cfg,
handle->accounts_tail = NULL;
handle->current = NULL;
- handle->creation_op = NULL;
handle->monitor = NULL;
handle->lobbies_head = NULL;
@@ -154,25 +155,36 @@ handle_destroy (struct GNUNET_CHAT_Handle *handle)
if (handle->shutdown_hook)
GNUNET_SCHEDULER_cancel(handle->shutdown_hook);
+ if (handle->destruction)
+ GNUNET_SCHEDULER_cancel(handle->destruction);
+
if (handle->monitor)
GNUNET_NAMESTORE_zone_monitor_stop(handle->monitor);
- if (handle->creation_op)
- GNUNET_IDENTITY_cancel(handle->creation_op);
-
if (handle->current)
handle_disconnect(handle);
if (handle->namestore)
GNUNET_NAMESTORE_disconnect(handle->namestore);
+ struct GNUNET_CHAT_InternalAccounts *accounts;
+ accounts = handle->accounts_head;
+
+ while (accounts)
+ {
+ if (accounts->op)
+ GNUNET_IDENTITY_cancel(accounts->op);
+
+ accounts->op = NULL;
+ accounts = accounts->next;
+ }
+
if (handle->identity)
GNUNET_IDENTITY_disconnect(handle->identity);
if (handle->arm)
GNUNET_ARM_disconnect(handle->arm);
- struct GNUNET_CHAT_InternalAccounts *accounts;
while (handle->accounts_head)
{
accounts = handle->accounts_head;
diff --git a/src/gnunet_chat_handle.h b/src/gnunet_chat_handle.h
index 5702206..2cc6349 100644
--- a/src/gnunet_chat_handle.h
+++ b/src/gnunet_chat_handle.h
@@ -56,6 +56,10 @@ struct GNUNET_CHAT_InternalMessages
struct GNUNET_CHAT_InternalAccounts
{
struct GNUNET_CHAT_Account *account;
+
+ struct GNUNET_CHAT_Handle *handle;
+ struct GNUNET_IDENTITY_Operation *op;
+
struct GNUNET_CHAT_InternalAccounts *next;
struct GNUNET_CHAT_InternalAccounts *prev;
};
@@ -82,6 +86,7 @@ struct GNUNET_CHAT_Handle
{
const struct GNUNET_CONFIGURATION_Handle* cfg;
struct GNUNET_SCHEDULER_Task *shutdown_hook;
+ struct GNUNET_SCHEDULER_Task *destruction;
struct GNUNET_CHAT_InternalMessages *internal_head;
struct GNUNET_CHAT_InternalMessages *internal_tail;
@@ -95,7 +100,6 @@ struct GNUNET_CHAT_Handle
struct GNUNET_CHAT_InternalAccounts *accounts_tail;
const struct GNUNET_CHAT_Account *current;
- struct GNUNET_IDENTITY_Operation *creation_op;
struct GNUNET_NAMESTORE_ZoneMonitor *monitor;
struct GNUNET_CHAT_InternalLobbies *lobbies_head;
diff --git a/src/gnunet_chat_handle_intern.c b/src/gnunet_chat_handle_intern.c
index cf8a3b3..63758a8 100644
--- a/src/gnunet_chat_handle_intern.c
+++ b/src/gnunet_chat_handle_intern.c
@@ -224,6 +224,9 @@ on_handle_gnunet_identity(void *cls,
{
struct GNUNET_CHAT_Handle* handle = cls;
+ if (!name)
+ return;
+
if (!ego)
goto send_refresh;
@@ -248,6 +251,8 @@ on_handle_gnunet_identity(void *cls,
handle->accounts_tail,
accounts
);
+
+ GNUNET_free(accounts);
}
goto send_refresh;
@@ -267,6 +272,9 @@ skip_account:
accounts = GNUNET_new(struct GNUNET_CHAT_InternalAccounts);
accounts->account = account_create_from_ego(ego, name);
+ accounts->handle = handle;
+ accounts->op = NULL;
+
if (handle->directory)
account_update_directory(accounts->account, handle->directory);
diff --git a/src/gnunet_chat_lib.c b/src/gnunet_chat_lib.c
index 72db7cd..6739d15 100644
--- a/src/gnunet_chat_lib.c
+++ b/src/gnunet_chat_lib.c
@@ -67,10 +67,12 @@ GNUNET_CHAT_stop (struct GNUNET_CHAT_Handle *handle)
{
GNUNET_CHAT_VERSION_ASSERT();
- if (!handle)
+ if ((!handle) || (handle->destruction))
return;
- handle_destroy(handle);
+ handle->destruction = GNUNET_SCHEDULER_add_now(
+ task_handle_destruction, handle
+ );
}
@@ -93,23 +95,76 @@ GNUNET_CHAT_account_create (struct GNUNET_CHAT_Handle *handle,
(0 == strcmp(accounts->account->name, name)))
return GNUNET_NO;
-skip_account:
+ skip_account:
accounts = accounts->next;
}
- if (handle->creation_op)
- GNUNET_IDENTITY_cancel(handle->creation_op);
+ accounts = GNUNET_new(struct GNUNET_CHAT_InternalAccounts);
+ accounts->account = NULL;
+ accounts->handle = handle;
- handle->creation_op = GNUNET_IDENTITY_create(
+ accounts->op = GNUNET_IDENTITY_create(
handle->identity,
name,
NULL,
GNUNET_IDENTITY_TYPE_ECDSA,
cb_account_creation,
- handle
+ accounts
+ );
+
+ if (!(accounts->op))
+ {
+ GNUNET_free(accounts);
+ return GNUNET_SYSERR;
+ }
+
+ GNUNET_CONTAINER_DLL_insert_tail(
+ handle->accounts_head,
+ handle->accounts_tail,
+ accounts
+ );
+
+ return GNUNET_OK;
+}
+
+
+int
+GNUNET_CHAT_account_delete(struct GNUNET_CHAT_Handle *handle,
+ const char* name)
+{
+ GNUNET_CHAT_VERSION_ASSERT();
+
+ if ((!handle) || (!name))
+ return GNUNET_SYSERR;
+
+ struct GNUNET_CHAT_InternalAccounts *accounts = handle->accounts_head;
+ while (accounts)
+ {
+ if (!(accounts->account))
+ goto skip_account;
+
+ if ((accounts->account->name) &&
+ (0 == strcmp(accounts->account->name, name)))
+ break;
+
+ skip_account:
+ accounts = accounts->next;
+ }
+
+ if (!accounts)
+ return GNUNET_NO;
+
+ if (accounts->op)
+ GNUNET_IDENTITY_cancel(accounts->op);
+
+ accounts->op = GNUNET_IDENTITY_delete(
+ handle->identity,
+ name,
+ cb_account_deletion,
+ accounts
);
- return (handle->creation_op? GNUNET_OK : GNUNET_SYSERR);
+ return (accounts->op? GNUNET_OK : GNUNET_SYSERR);
}
@@ -129,13 +184,14 @@ GNUNET_CHAT_iterate_accounts (const struct GNUNET_CHAT_Handle *handle,
while (accounts)
{
if (!(accounts->account))
- return GNUNET_SYSERR;
+ goto skip_account;
result++;
if ((callback) && (GNUNET_YES != callback(cls, handle, accounts->account)))
break;
+ skip_account:
accounts = accounts->next;
}
diff --git a/src/gnunet_chat_lib_intern.c b/src/gnunet_chat_lib_intern.c
index 444f3c0..a430fe5 100644
--- a/src/gnunet_chat_lib_intern.c
+++ b/src/gnunet_chat_lib_intern.c
@@ -25,15 +25,36 @@
#define GNUNET_UNUSED __attribute__ ((unused))
void
+task_handle_destruction (void *cls)
+{
+ GNUNET_assert(cls);
+
+ struct GNUNET_CHAT_Handle *handle = (struct GNUNET_CHAT_Handle*) cls;
+
+ handle->destruction = NULL;
+ handle_destroy(handle);
+}
+
+void
cb_account_creation (void *cls,
const struct GNUNET_IDENTITY_PrivateKey *key,
const char *emsg)
{
GNUNET_assert(cls);
- struct GNUNET_CHAT_Handle *handle = (struct GNUNET_CHAT_Handle*) cls;
+ struct GNUNET_CHAT_InternalAccounts *accounts = (
+ (struct GNUNET_CHAT_InternalAccounts*) cls
+ );
- handle->creation_op = NULL;
+ struct GNUNET_CHAT_Handle *handle = accounts->handle;
+
+ GNUNET_CONTAINER_DLL_remove(
+ handle->accounts_head,
+ handle->accounts_tail,
+ accounts
+ );
+
+ GNUNET_free(accounts);
if (emsg)
handle_send_internal_message(handle, NULL, GNUNET_CHAT_FLAG_WARNING, emsg);
@@ -42,6 +63,35 @@ cb_account_creation (void *cls,
}
void
+cb_account_deletion (void *cls,
+ const char *emsg)
+{
+ GNUNET_assert(cls);
+
+ struct GNUNET_CHAT_InternalAccounts *accounts = (
+ (struct GNUNET_CHAT_InternalAccounts*) cls
+ );
+
+ struct GNUNET_CHAT_Handle *handle = accounts->handle;
+
+ if (emsg)
+ {
+ handle_send_internal_message(handle, NULL, GNUNET_CHAT_FLAG_WARNING, emsg);
+ return;
+ }
+
+ GNUNET_CONTAINER_DLL_remove(
+ handle->accounts_head,
+ handle->accounts_tail,
+ accounts
+ );
+
+ GNUNET_free(accounts);
+
+ handle_send_internal_message(handle, NULL, GNUNET_CHAT_FLAG_REFRESH, NULL);
+}
+
+void
cb_lobby_lookup (void *cls,
uint32_t count,
const struct GNUNET_GNSRECORD_Data *data)
diff --git a/tests/test_gnunet_chat.h b/tests/test_gnunet_chat.h
index 80803d3..2172611 100644
--- a/tests/test_gnunet_chat.h
+++ b/tests/test_gnunet_chat.h
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2021 GNUnet e.V.
+ Copyright (C) 2021--2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -32,6 +32,8 @@
#include <gnunet/gnunet_chat_lib.h>
+#define GNUNET_CHAT_TEST_ACCOUNT "check"
+
#define CREATE_GNUNET_TEST(test_name, test_call) \
void \
task_##test_call (__attribute__ ((unused)) void *cls, \
diff --git a/tests/test_gnunet_chat_handle.c b/tests/test_gnunet_chat_handle.c
index efa2ba9..f8a7b60 100644
--- a/tests/test_gnunet_chat_handle.c
+++ b/tests/test_gnunet_chat_handle.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2021 GNUnet e.V.
+ Copyright (C) 2021--2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -37,104 +37,134 @@ call_gnunet_chat_handle_init(const struct GNUNET_CONFIGURATION_Handle *cfg)
CREATE_GNUNET_TEST(test_gnunet_chat_handle_init, call_gnunet_chat_handle_init)
-struct GNUNET_CHAT_Handle *login_handle;
+struct GNUNET_CHAT_Handle *accounts_handle;
+int accounts_stage;
int
-on_gnunet_chat_handle_login_msg(void *cls,
- struct GNUNET_CHAT_Context *context,
- const struct GNUNET_CHAT_Message *message)
+on_gnunet_chat_handle_accounts_it(__attribute__ ((unused)) void *cls,
+ __attribute__ ((unused)) const struct GNUNET_CHAT_Handle *handle,
+ struct GNUNET_CHAT_Account *account)
+{
+ const char *name = GNUNET_CHAT_account_get_name(account);
+
+ ck_assert_ptr_ne(name, NULL);
+
+ if (0 == strcmp(name, GNUNET_CHAT_TEST_ACCOUNT))
+ accounts_stage |= 2;
+
+ return GNUNET_YES;
+}
+
+int
+on_gnunet_chat_handle_accounts_msg(void *cls,
+ struct GNUNET_CHAT_Context *context,
+ const struct GNUNET_CHAT_Message *message)
{
enum GNUNET_CHAT_MessageKind kind = GNUNET_CHAT_message_get_kind(message);
- ck_assert(kind == GNUNET_CHAT_KIND_LOGIN);
+ ck_assert(kind == GNUNET_CHAT_KIND_REFRESH);
ck_assert_ptr_eq(cls, NULL);
ck_assert_ptr_eq(context, NULL);
- GNUNET_CHAT_stop(login_handle);
+ GNUNET_CHAT_iterate_accounts(
+ accounts_handle,
+ on_gnunet_chat_handle_accounts_it,
+ NULL
+ );
+
+ if (2 & accounts_stage)
+ {
+ if (3 == accounts_stage)
+ ck_assert_int_eq(GNUNET_CHAT_account_delete(
+ accounts_handle,
+ GNUNET_CHAT_TEST_ACCOUNT
+ ), GNUNET_OK);
+
+ accounts_stage = 4;
+ }
+ else if (4 == accounts_stage)
+ GNUNET_CHAT_stop(accounts_handle);
+ else if (0 == accounts_stage)
+ {
+ ck_assert_int_eq(GNUNET_CHAT_account_create(
+ accounts_handle,
+ GNUNET_CHAT_TEST_ACCOUNT
+ ), GNUNET_OK);
+
+ accounts_stage = 1;
+ }
+
return GNUNET_YES;
}
void
-call_gnunet_chat_handle_login(const struct GNUNET_CONFIGURATION_Handle *cfg)
+call_gnunet_chat_handle_accounts(const struct GNUNET_CONFIGURATION_Handle *cfg)
{
- login_handle = GNUNET_CHAT_start(cfg, on_gnunet_chat_handle_login_msg, NULL);
- ck_assert_ptr_ne(login_handle, NULL);
+ accounts_handle = GNUNET_CHAT_start(cfg, on_gnunet_chat_handle_accounts_msg, NULL);
+ accounts_stage = 0;
+
+ ck_assert_ptr_ne(accounts_handle, NULL);
}
-CREATE_GNUNET_TEST(test_gnunet_chat_handle_login, call_gnunet_chat_handle_login)
+CREATE_GNUNET_TEST(test_gnunet_chat_handle_accounts, call_gnunet_chat_handle_accounts)
-struct GNUNET_CHAT_Handle *access_handle;
-int access_logins;
+struct GNUNET_CHAT_Handle *connection_handle;
int
-on_gnunet_chat_handle_access_msg(void *cls,
- struct GNUNET_CHAT_Context *context,
- const struct GNUNET_CHAT_Message *message)
+on_gnunet_chat_handle_connection_msg(void *cls,
+ struct GNUNET_CHAT_Context *context,
+ const struct GNUNET_CHAT_Message *message)
{
enum GNUNET_CHAT_MessageKind kind = GNUNET_CHAT_message_get_kind(message);
+ ck_assert(kind == GNUNET_CHAT_KIND_LOGIN);
ck_assert_ptr_eq(cls, NULL);
ck_assert_ptr_eq(context, NULL);
- const char *key;
- const char *name;
- int result;
-
- if (access_logins == 0)
- {
- ck_assert(kind == GNUNET_CHAT_KIND_LOGIN);
-
- key = GNUNET_CHAT_get_key(access_handle);
- ck_assert_ptr_eq(key, NULL);
-
- result = GNUNET_CHAT_update(access_handle);
- ck_assert_int_eq(result, GNUNET_OK);
-
- name = GNUNET_CHAT_get_name(access_handle);
- ck_assert_str_eq(name, "Access");
- }
- else if (access_logins == 1)
- {
- ck_assert(kind == GNUNET_CHAT_KIND_LOGIN);
+ GNUNET_CHAT_stop(connection_handle);
+ return GNUNET_YES;
+}
- key = GNUNET_CHAT_get_key(access_handle);
- ck_assert_ptr_ne(key, NULL);
+void
+call_gnunet_chat_handle_connection(const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ connection_handle = GNUNET_CHAT_start(cfg, on_gnunet_chat_handle_connection_msg, NULL);
+ ck_assert_ptr_ne(connection_handle, NULL);
+}
- result = GNUNET_CHAT_set_name(access_handle, "Bccess");
- ck_assert_int_eq(result, GNUNET_YES);
- }
- else
- {
- ck_assert(kind == GNUNET_CHAT_KIND_CONTACT);
+CREATE_GNUNET_TEST(test_gnunet_chat_handle_connection, call_gnunet_chat_handle_connection)
- ck_assert_int_eq(access_logins, 2);
+struct GNUNET_CHAT_Handle *update_handle;
- name = GNUNET_CHAT_get_name(access_handle);
- ck_assert_str_eq(name, "Bccess");
+int
+on_gnunet_chat_handle_update_msg(void *cls,
+ struct GNUNET_CHAT_Context *context,
+ const struct GNUNET_CHAT_Message *message)
+{
+ enum GNUNET_CHAT_MessageKind kind = GNUNET_CHAT_message_get_kind(message);
- GNUNET_CHAT_stop(access_handle);
- }
+ ck_assert_ptr_eq(cls, NULL);
+ ck_assert_ptr_eq(context, NULL);
- access_logins++;
+ GNUNET_CHAT_stop(update_handle);
return GNUNET_YES;
}
void
-call_gnunet_chat_handle_access(const struct GNUNET_CONFIGURATION_Handle *cfg)
+call_gnunet_chat_handle_update(const struct GNUNET_CONFIGURATION_Handle *cfg)
{
- access_logins = 0;
-
- access_handle = GNUNET_CHAT_start(cfg, on_gnunet_chat_handle_access_msg, NULL);
- ck_assert_ptr_ne(access_handle, NULL);
+ update_handle = GNUNET_CHAT_start(cfg, on_gnunet_chat_handle_update_msg, NULL);
+ ck_assert_ptr_ne(update_handle, NULL);
}
-CREATE_GNUNET_TEST(test_gnunet_chat_handle_access, call_gnunet_chat_handle_access)
+CREATE_GNUNET_TEST(test_gnunet_chat_handle_update, call_gnunet_chat_handle_update)
START_SUITE(handle_suite, "Handle")
ADD_TEST_TO_SUITE(test_gnunet_chat_handle_init, "Start/Stop")
-ADD_TEST_TO_SUITE(test_gnunet_chat_handle_login, "Login")
-ADD_TEST_TO_SUITE(test_gnunet_chat_handle_access, "Get/Set")
+ADD_TEST_TO_SUITE(test_gnunet_chat_handle_accounts, "Accounts")
+ADD_TEST_TO_SUITE(test_gnunet_chat_handle_connection, "Connect/Disconnect")
+ADD_TEST_TO_SUITE(test_gnunet_chat_handle_update, "Update")
END_SUITE
MAIN_SUITE(handle_suite, CK_NORMAL)