diff --git a/accelerator/core/apis.c b/accelerator/core/apis.c index 563e57b5..ac5b8984 100644 --- a/accelerator/core/apis.c +++ b/accelerator/core/apis.c @@ -394,6 +394,33 @@ status_t api_fetch_txn_with_uuid(const ta_cache_t* const cache, const char* cons return ret; } +status_t api_register_mam_channel(const ta_cache_t* const cache, const char* const obj, char** json_result) { + status_t ret = SC_OK; + ta_register_mam_channel_req_t* req = ta_register_mam_channel_req_new(); + char uuid[UUID_STR_LEN]; + + ret = register_mam_channel_req_deserialize(obj, req); + if (ret) { + ta_log_error("Failed to deserialize request.\n"); + goto done; + } + + ret = ta_register_mam_channel(cache, req, uuid); + if (ret) { + ta_log_error("%s\n", ta_error_to_string(ret)); + goto done; + } + + ret = register_mam_channel_res_serialize(uuid, json_result); + if (ret) { + ta_log_error("Failed to deserialize request.\n"); + } + +done: + ta_register_mam_channel_req_free(&req); + return ret; +} + #ifdef DB_ENABLE status_t api_find_transactions_by_id(const iota_client_service_t* const iota_service, const db_client_service_t* const db_service, const char* const obj, diff --git a/accelerator/core/apis.h b/accelerator/core/apis.h index fb462387..a9091afa 100644 --- a/accelerator/core/apis.h +++ b/accelerator/core/apis.h @@ -213,6 +213,19 @@ status_t api_get_node_status(const iota_client_service_t* const service, char** */ status_t api_fetch_txn_with_uuid(const ta_cache_t* const cache, const char* const uuid, char** json_result); +/** + * @brief Register user identity with MAM channel seed + * + * @param[in] cache Redis configuration variables + * @param[in] obj Request in JSON format + * @param[out] json_result Result contains the user id. + * + * @return + * - SC_OK on success + * - non-zero on error + */ +status_t api_register_mam_channel(const ta_cache_t* const cache, const char* const obj, char** json_result); + #ifdef DB_ENABLE /** * @brief Return transaction object with given single identity number. diff --git a/accelerator/core/core.c b/accelerator/core/core.c index 46ce5a01..7f18c135 100644 --- a/accelerator/core/core.c +++ b/accelerator/core/core.c @@ -565,9 +565,9 @@ status_t push_txn_to_buffer(const ta_cache_t* const cache, hash8019_array_p raw_ goto done; } - uuid_t binuuid; - uuid_generate_random(binuuid); - uuid_unparse(binuuid, uuid); + uuid_t bin_uuid; + uuid_generate_random(bin_uuid); + uuid_unparse(bin_uuid, uuid); if (!uuid[0]) { ta_log_error("%s\n", "Failed to generate UUID"); goto done; diff --git a/accelerator/core/mam_core.c b/accelerator/core/mam_core.c index 54cd2a6b..ca4c52e4 100644 --- a/accelerator/core/mam_core.c +++ b/accelerator/core/mam_core.c @@ -776,3 +776,29 @@ status_t ta_recv_mam_message(const iota_config_t *const iconf, const iota_client mam_encrypt_key_free(&mam_key); return ret; } + +status_t ta_register_mam_channel(const ta_cache_t *const cache, const ta_register_mam_channel_req_t *const req, + char *uuid) { + if (!cache || !req || !uuid) { + ta_log_error("%s\n", ta_error_to_string(SC_NULL)); + return SC_NULL; + } + status_t ret = SC_OK; + + uuid_t bin_uuid; + uuid_generate_random(bin_uuid); + uuid_unparse(bin_uuid, uuid); + if (!uuid[0]) { + ta_log_error("%s\n", "Failed to generate UUID"); + goto done; + } + + ret = cache_set(uuid, UUID_STR_LEN - 1, req->seed, NUM_TRYTES_ADDRESS, cache->timeout); + if (ret) { + ta_log_error("%s\n", ta_error_to_string(ret)); + goto done; + } + +done: + return ret; +} diff --git a/accelerator/core/mam_core.h b/accelerator/core/mam_core.h index 242537c9..6b0c0e4f 100644 --- a/accelerator/core/mam_core.h +++ b/accelerator/core/mam_core.h @@ -79,6 +79,20 @@ status_t ta_send_mam_message(const ta_config_t* const info, const iota_config_t* status_t ta_recv_mam_message(const iota_config_t* const iconf, const iota_client_service_t* const service, ta_recv_mam_req_t* const req, ta_recv_mam_res_t* const res); +/** + * @brief Register user identity with MAM channel seed. + * + * @param[in] cache redis configuration variables + * @param[in] req Request in 'ta_register_mam_channel_req_t' datatype + * @param[out] uuid Returned UUID + * + * @return + * - SC_OK on success + * - non-zero on error + */ +status_t ta_register_mam_channel(const ta_cache_t* const cache, const ta_register_mam_channel_req_t* const req, + char* uuid); + #ifdef __cplusplus } #endif diff --git a/accelerator/core/request/request.h b/accelerator/core/request/request.h index 349be492..8653b24f 100644 --- a/accelerator/core/request/request.h +++ b/accelerator/core/request/request.h @@ -11,6 +11,7 @@ #include "ta_find_transaction_objects.h" #include "ta_recv_mam.h" +#include "ta_register_mam_channel.h" #include "ta_send_mam.h" #include "ta_send_transfer.h" diff --git a/accelerator/core/request/ta_register_mam_channel.c b/accelerator/core/request/ta_register_mam_channel.c new file mode 100644 index 00000000..48e716c5 --- /dev/null +++ b/accelerator/core/request/ta_register_mam_channel.c @@ -0,0 +1,17 @@ +#include "ta_register_mam_channel.h" + +ta_register_mam_channel_req_t* ta_register_mam_channel_req_new() { + ta_register_mam_channel_req_t* req = (ta_register_mam_channel_req_t*)malloc(sizeof(ta_register_mam_channel_req_t)); + if (req != NULL) { + return req; + } + return NULL; +} + +void ta_register_mam_channel_req_free(ta_register_mam_channel_req_t** req) { + if (!req || !(*req)) { + return; + } + free(*req); + *req = NULL; +} diff --git a/accelerator/core/request/ta_register_mam_channel.h b/accelerator/core/request/ta_register_mam_channel.h new file mode 100644 index 00000000..aba3f86e --- /dev/null +++ b/accelerator/core/request/ta_register_mam_channel.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2020 BiiLabs Co., Ltd. and Contributors + * All Rights Reserved. + * This is free software; you can redistribute it and/or modify it under the + * terms of the MIT license. A copy of the license can be found in the file + * "LICENSE" at the root of this distribution. + */ + +#ifndef REQUEST_TA_REGISTER_MAM_CHANNEL_H_ +#define REQUEST_TA_REGISTER_MAM_CHANNEL_H_ + +#include "common/model/transaction.h" +#include "common/ta_errors.h" +#include "utils/containers/hash/hash243_queue.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file accelerator/core/request/ta_register_mam_channel.h + */ + +/** struct of ta_register_mam_channel_req_t */ +typedef struct ta_register_mam_channel_req { + char seed[NUM_TRYTES_ADDRESS + 1]; +} ta_register_mam_channel_req_t; + +/** + * @brief Allocate memory of ta_register_mam_channel_req_t + * + * @return + * - struct of ta_register_mam_channel_req_t on success + * - NULL on error + */ +ta_register_mam_channel_req_t* ta_register_mam_channel_req_new(); + +/** + * @brief Free memory of ta_register_mam_channel_req_t + * + * @param[in] req Data type of ta_register_mam_channel_req_t + */ +void ta_register_mam_channel_req_free(ta_register_mam_channel_req_t** req); + +#ifdef __cplusplus +} +#endif + +#endif // REQUEST_TA_REGISTER_MAM_CHANNEL_H_ diff --git a/accelerator/core/serializer/ser_mam.c b/accelerator/core/serializer/ser_mam.c index 27f92b16..cd8a6c55 100644 --- a/accelerator/core/serializer/ser_mam.c +++ b/accelerator/core/serializer/ser_mam.c @@ -482,3 +482,94 @@ status_t recv_mam_message_res_serialize(ta_recv_mam_res_t* const res, char** obj cJSON_Delete(json_root); return ret; } + +status_t register_mam_channel_req_deserialize(const char* const obj, ta_register_mam_channel_req_t* req) { + if (obj == NULL || req == NULL) { + ta_log_error("%s\n", ta_error_to_string(SC_SERIALIZER_NULL)); + return SC_SERIALIZER_NULL; + } + status_t ret = SC_OK; + cJSON* json_obj = cJSON_Parse(obj); + cJSON* json_item = NULL; + + if (json_obj == NULL) { + ret = SC_SERIALIZER_JSON_PARSE; + ta_log_error("%s\n", ta_error_to_string(ret)); + goto done; + } + + json_item = cJSON_GetObjectItemCaseSensitive(json_obj, "seed"); + if (json_item == NULL) { + ret = SC_SERIALIZER_KEY_NOT_EXISTS; + ta_log_error("%s\n", ta_error_to_string(ret)); + } else if (json_item->valuestring == NULL) { + ret = SC_SERIALIZER_VALUE_EMPTY; + ta_log_error("%s\n", ta_error_to_string(ret)); + } else if (strlen(json_item->valuestring) != NUM_TRYTES_ADDRESS) { + ret = SC_SERIALIZER_VALUE_INVLID; + ta_log_error("%s\n", ta_error_to_string(ret)); + } else { + strncpy(req->seed, json_item->valuestring, NUM_TRYTES_ADDRESS); + req->seed[NUM_TRYTES_ADDRESS] = 0; + } + +done: + cJSON_Delete(json_obj); + return ret; +} + +status_t register_mam_channel_res_serialize(const char* const uuid, char** obj) { + if (uuid == NULL) { + ta_log_error("%s\n", ta_error_to_string(SC_SERIALIZER_NULL)); + return SC_SERIALIZER_NULL; + } + + status_t ret = SC_OK; + cJSON* json_root = cJSON_CreateObject(); + + cJSON_AddStringToObject(json_root, "user-id", uuid); + + *obj = cJSON_PrintUnformatted(json_root); + if (*obj == NULL) { + ta_log_error("%s\n", ta_error_to_string(SC_SERIALIZER_JSON_PARSE)); + ret = SC_SERIALIZER_JSON_PARSE; + } + + cJSON_Delete(json_root); + return ret; +} + +status_t register_mam_channel_res_deserialize(const char* const obj, char* user_id) { + if (obj == NULL || user_id == NULL) { + ta_log_error("%s\n", ta_error_to_string(SC_SERIALIZER_NULL)); + return SC_SERIALIZER_NULL; + } + status_t ret = SC_OK; + cJSON* json_obj = cJSON_Parse(obj); + cJSON* json_item = NULL; + + if (json_obj == NULL) { + ret = SC_SERIALIZER_JSON_PARSE; + ta_log_error("%s\n", ta_error_to_string(ret)); + goto done; + } + + json_item = cJSON_GetObjectItemCaseSensitive(json_obj, "user-id"); + if (json_item == NULL) { + ret = SC_SERIALIZER_KEY_NOT_EXISTS; + ta_log_error("%s\n", ta_error_to_string(ret)); + } else if (json_item->valuestring == NULL) { + ret = SC_SERIALIZER_VALUE_EMPTY; + ta_log_error("%s\n", ta_error_to_string(ret)); + } else if (strlen(json_item->valuestring) != UUID_STR_LEN - 1) { + ret = SC_SERIALIZER_VALUE_INVLID; + ta_log_error("%s\n", ta_error_to_string(ret)); + } else { + strncpy(user_id, json_item->valuestring, UUID_STR_LEN - 1); + user_id[UUID_STR_LEN - 1] = 0; + } + +done: + cJSON_Delete(json_obj); + return ret; +} diff --git a/accelerator/core/serializer/ser_mam.h b/accelerator/core/serializer/ser_mam.h index 03b2e645..c6f73074 100644 --- a/accelerator/core/serializer/ser_mam.h +++ b/accelerator/core/serializer/ser_mam.h @@ -93,6 +93,54 @@ status_t recv_mam_message_res_deserialize(const char* const obj, ta_recv_mam_res */ status_t recv_mam_message_res_serialize(ta_recv_mam_res_t* const res, char** obj); +/** + * @brief Deserialize JSON string to type of ta_send_mam_req_t + * + * @param[in] obj Input values in JSON + * @param[out] req Request data in type of ta_send_mam_req_t + * + * @return + * - SC_OK on success + * - non-zero on error + */ +status_t send_mam_message_req_deserialize(const char* const obj, ta_send_mam_req_t* req); + +/** + * @brief Deserialize JSON string to type of ta_register_mam_channel_req_t + * + * @param[in] obj Input values in JSON + * @param[out] req Request data in type of ta_register_mam_channel_req_t + * + * @return + * - SC_OK on success + * - non-zero on error + */ +status_t register_mam_channel_req_deserialize(const char* const obj, ta_register_mam_channel_req_t* req); + +/** + * @brief Serialize response of register_mam_channel + * + * @param[in] uuid Returned UUID from tangle-accelerator + * @param[out] obj Response formed in JSON + * + * @return + * - SC_OK on success + * - non-zero on error + */ +status_t register_mam_channel_res_serialize(const char* const uuid, char** obj); + +/** + * @brief Deserialize JSON string to user-id + * + * @param[in] obj Input values in JSON + * @param[out] user_id User ID in string + * + * @return + * - SC_OK on success + * - non-zero on error + */ +status_t register_mam_channel_res_deserialize(const char* const obj, char* user_id); + #ifdef __cplusplus } #endif diff --git a/common/ta_errors.h b/common/ta_errors.h index 51c2290f..361c491b 100644 --- a/common/ta_errors.h +++ b/common/ta_errors.h @@ -114,6 +114,12 @@ typedef enum { /**< Invald request value in JSON */ SC_SERIALIZER_MESSAGE_OVERRUN = 0x06 | SC_MODULE_SERIALIZER | SC_SEVERITY_FATAL, /**< Message length is out of valid size */ + SC_SERIALIZER_KEY_NOT_EXISTS = 0x07 | SC_MODULE_SERIALIZER | SC_SEVERITY_FATAL, + /**< Expected key doesn't exist */ + SC_SERIALIZER_VALUE_EMPTY = 0x08 | SC_MODULE_SERIALIZER | SC_SEVERITY_FATAL, + /**< The value of the given key is empty */ + SC_SERIALIZER_VALUE_INVLID = 0x08 | SC_MODULE_SERIALIZER | SC_SEVERITY_FATAL, + /**< The value or length of the value is invalid */ // Cache module SC_CACHE_FAILED_RESPONSE = 0x02 | SC_MODULE_CACHE | SC_SEVERITY_FATAL, diff --git a/tests/api/mam_test.c b/tests/api/mam_test.c index 74e05617..c410ec21 100644 --- a/tests/api/mam_test.c +++ b/tests/api/mam_test.c @@ -230,6 +230,18 @@ void test_encrypt_decrypt_psk(void) { send_mam_res_free(&send_res); } +void test_api_register_mam_channel(void) { + char* json_result; + const char* json = "{\"seed\":\"" TRYTES_81_1 "\"}"; + char user_id[UUID_STR_LEN], seed[NUM_TRYTES_ADDRESS + 1]; + TEST_ASSERT_EQUAL_INT32(SC_OK, api_register_mam_channel(&ta_core.cache, json, &json_result)); + + TEST_ASSERT_EQUAL_INT32(SC_OK, register_mam_channel_res_deserialize(json_result, user_id)); + TEST_ASSERT_EQUAL_INT32(SC_OK, cache_get(user_id, seed)); + TEST_ASSERT_EQUAL_INT32(SC_OK, cache_del(user_id)); + free(json_result); +} + int main(int argc, char* argv[]) { UNITY_BEGIN(); rand_trytes_init(); @@ -251,6 +263,7 @@ int main(int argc, char* argv[]) { RUN_TEST(test_write_until_next_channel); RUN_TEST(test_write_with_chid); RUN_TEST(test_encrypt_decrypt_psk); + RUN_TEST(test_api_register_mam_channel); ta_core_destroy(&ta_core); return UNITY_END(); } diff --git a/tests/unit-test/test_cache.c b/tests/unit-test/test_cache.c index 4c7e1097..3d630d4e 100644 --- a/tests/unit-test/test_cache.c +++ b/tests/unit-test/test_cache.c @@ -43,9 +43,9 @@ void test_cache_timeout(void) { } void test_generate_uuid(void) { - uuid_t binuuid; - uuid_generate_random(binuuid); - uuid_unparse(binuuid, test_uuid); + uuid_t bin_uuid; + uuid_generate_random(bin_uuid); + uuid_unparse(bin_uuid, test_uuid); TEST_ASSERT_TRUE(test_uuid[0]); } diff --git a/tests/unit-test/test_serializer.c b/tests/unit-test/test_serializer.c index c098b83f..6187f4b8 100644 --- a/tests/unit-test/test_serializer.c +++ b/tests/unit-test/test_serializer.c @@ -357,7 +357,6 @@ void test_send_mam_message_request_deserialize(void) { "\",\"message\":\"" TEST_PAYLOAD "\",\"ch_mss_depth\":" STR(TEST_CH_DEPTH) ",\"ep_mss_depth\":" STR( TEST_EP_DEPTH) "},\"key\":{\"ntru\":[\"" TEST_NTRU_PK "\"],\"psk\":[\"" TRYTES_81_2 "\",\"" TRYTES_81_3 "\"]}, \"protocol\":\"MAM_V1\"}"; - printf("json = %s\n", json); ta_send_mam_req_t* req = send_mam_req_new(); send_mam_message_req_deserialize(json, req); send_mam_data_mam_v1_t* data = (send_mam_data_mam_v1_t*)req->data; @@ -622,6 +621,23 @@ void test_fetch_txn_with_uuid_res_not_exist_serialize(void) { free(json_result); } +void test_register_mam_channel_req_deserialize(void) { + const char* json = "{\"seed\":\"" TRYTES_81_1 "\"}"; + ta_register_mam_channel_req_t* req = ta_register_mam_channel_req_new(); + + TEST_ASSERT_EQUAL_INT32(SC_OK, register_mam_channel_req_deserialize(json, req)); + TEST_ASSERT_EQUAL_STRING(TRYTES_81_1, req->seed); + ta_register_mam_channel_req_free(&req); +} + +void test_register_mam_channel_res_serialize(void) { + const char* json = "{\"user-id\":\"" TEST_UUID "\"}"; + char* json_result = NULL; + TEST_ASSERT_EQUAL_INT32(SC_OK, register_mam_channel_res_serialize(TEST_UUID, &json_result)); + TEST_ASSERT_EQUAL_STRING(json, json_result); + free(json_result); +} + int main(void) { UNITY_BEGIN(); @@ -657,6 +673,8 @@ int main(void) { RUN_TEST(test_get_node_status_res_serialize); RUN_TEST(test_fetch_txn_with_uuid_res_sent_serialize); RUN_TEST(test_fetch_txn_with_uuid_res_not_exist_serialize); + RUN_TEST(test_register_mam_channel_req_deserialize); + RUN_TEST(test_register_mam_channel_res_serialize); serializer_logger_release(); return UNITY_END(); }