Skip to content
This repository was archived by the owner on Dec 26, 2022. It is now read-only.

Commit 9d0c9c4

Browse files
committed
feat(api): Add lock to avoid race condition
1 parent 2514a9a commit 9d0c9c4

File tree

5 files changed

+106
-0
lines changed

5 files changed

+106
-0
lines changed

accelerator/apis.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88

99
#include "apis.h"
1010
#include "map/mode.h"
11+
#include "utils/handles/lock.h"
1112

1213
#define APIS_LOGGER "apis"
1314

1415
static logger_id_t apis_logger_id;
16+
lock_handle_t cjson_lock;
1517

1618
void apis_logger_init() { apis_logger_id = logger_helper_enable(APIS_LOGGER, LOGGER_DEBUG, true); }
1719

@@ -38,6 +40,20 @@ status_t api_get_ta_info(char** json_result, ta_config_t* const info, iota_confi
3840
return ret;
3941
}
4042

43+
status_t apis_lock_init() {
44+
if (lock_handle_init(&cjson_lock)) {
45+
return SC_CONF_LOCK_INIT;
46+
}
47+
return SC_OK;
48+
}
49+
50+
status_t apis_lock_destroy() {
51+
if (lock_handle_destroy(&cjson_lock)) {
52+
return SC_CONF_LOCK_DESTROY;
53+
}
54+
return SC_OK;
55+
}
56+
4157
status_t api_get_tips(const iota_client_service_t* const service, char** json_result) {
4258
status_t ret = SC_OK;
4359
get_tips_res_t* res = get_tips_res_new();
@@ -48,11 +64,14 @@ status_t api_get_tips(const iota_client_service_t* const service, char** json_re
4864
goto done;
4965
}
5066

67+
lock_handle_lock(&cjson_lock);
5168
if (iota_client_get_tips(service, res) != RC_OK) {
69+
lock_handle_unlock(&cjson_lock);
5270
ret = SC_CCLIENT_FAILED_RESPONSE;
5371
log_error(apis_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_CCLIENT_FAILED_RESPONSE");
5472
goto done;
5573
}
74+
lock_handle_unlock(&cjson_lock);
5675

5776
ret = ta_get_tips_res_serialize(res, json_result);
5877
if (ret != SC_OK) {
@@ -80,11 +99,14 @@ status_t api_get_tips_pair(const iota_config_t* const tangle, const iota_client_
8099
}
81100

82101
get_transactions_to_approve_req_set_depth(req, tangle->milestone_depth);
102+
lock_handle_lock(&cjson_lock);
83103
if (iota_client_get_transactions_to_approve(service, req, res) != RC_OK) {
104+
lock_handle_unlock(&cjson_lock);
84105
ret = SC_CCLIENT_FAILED_RESPONSE;
85106
log_error(apis_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_CCLIENT_FAILED_RESPONSE");
86107
goto done;
87108
}
109+
lock_handle_unlock(&cjson_lock);
88110

89111
if (service->serializer.vtable.get_transactions_to_approve_serialize_response(res, res_buff) != RC_OK) {
90112
ret = SC_CCLIENT_JSON_PARSE;
@@ -117,10 +139,13 @@ status_t api_generate_address(const iota_config_t* const tangle, const iota_clie
117139
goto done;
118140
}
119141

142+
lock_handle_lock(&cjson_lock);
120143
ret = ta_generate_address(tangle, service, res);
121144
if (ret) {
145+
lock_handle_unlock(&cjson_lock);
122146
goto done;
123147
}
148+
lock_handle_unlock(&cjson_lock);
124149

125150
ret = ta_generate_address_res_serialize(res, json_result);
126151

@@ -139,17 +164,23 @@ status_t api_find_transactions(const iota_client_service_t* const service, const
139164
log_error(apis_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_TA_OOM");
140165
goto done;
141166
}
167+
lock_handle_lock(&cjson_lock);
142168
if (service->serializer.vtable.find_transactions_deserialize_request(obj, req) != RC_OK) {
169+
lock_handle_unlock(&cjson_lock);
143170
ret = SC_CCLIENT_JSON_PARSE;
144171
log_error(apis_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_CCLIENT_JSON_PARSE");
145172
goto done;
146173
}
174+
lock_handle_unlock(&cjson_lock);
147175

176+
lock_handle_lock(&cjson_lock);
148177
if (iota_client_find_transactions(service, req, res) != RC_OK) {
178+
lock_handle_unlock(&cjson_lock);
149179
ret = SC_CCLIENT_FAILED_RESPONSE;
150180
log_error(apis_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_CCLIENT_FAILED_RESPONSE");
151181
goto done;
152182
}
183+
lock_handle_unlock(&cjson_lock);
153184

154185
if (service->serializer.vtable.find_transactions_serialize_response(res, res_buff) != RC_OK) {
155186
ret = SC_CCLIENT_JSON_PARSE;
@@ -187,11 +218,14 @@ status_t api_find_transaction_object_single(const iota_client_service_t* const s
187218
flex_trits_from_trytes(txn_hash, NUM_TRITS_HASH, (const tryte_t*)obj, NUM_TRYTES_HASH, NUM_TRYTES_HASH);
188219
hash243_queue_push(&req->hashes, txn_hash);
189220

221+
lock_handle_lock(&cjson_lock);
190222
ret = ta_find_transaction_objects(service, req, res);
191223
if (ret) {
224+
lock_handle_unlock(&cjson_lock);
192225
log_error(apis_logger_id, "[%s:%d]\n", __func__, __LINE__);
193226
goto done;
194227
}
228+
lock_handle_unlock(&cjson_lock);
195229

196230
ret = ta_find_transaction_object_single_res_serialize(res, json_result);
197231

@@ -212,17 +246,23 @@ status_t api_find_transaction_objects(const iota_client_service_t* const service
212246
goto done;
213247
}
214248

249+
lock_handle_lock(&cjson_lock);
215250
ret = ta_find_transaction_objects_req_deserialize(obj, req);
216251
if (ret != SC_OK) {
252+
lock_handle_unlock(&cjson_lock);
217253
log_error(apis_logger_id, "[%s:%d]\n", __func__, __LINE__);
218254
goto done;
219255
}
256+
lock_handle_unlock(&cjson_lock);
220257

258+
lock_handle_lock(&cjson_lock);
221259
ret = ta_find_transaction_objects(service, req, res);
222260
if (ret) {
261+
lock_handle_unlock(&cjson_lock);
223262
log_error(apis_logger_id, "[%s:%d]\n", __func__, __LINE__);
224263
goto done;
225264
}
265+
lock_handle_unlock(&cjson_lock);
226266

227267
ret = ta_find_transaction_objects_res_serialize(res, json_result);
228268

@@ -251,11 +291,14 @@ status_t api_find_transactions_by_tag(const iota_client_service_t* const service
251291
goto done;
252292
}
253293

294+
lock_handle_lock(&cjson_lock);
254295
if (iota_client_find_transactions(service, req, res) != RC_OK) {
296+
lock_handle_unlock(&cjson_lock);
255297
ret = SC_CCLIENT_FAILED_RESPONSE;
256298
log_error(apis_logger_id, "[%s:%d]\n", __func__, __LINE__);
257299
goto done;
258300
}
301+
lock_handle_unlock(&cjson_lock);
259302

260303
ret = ta_find_transactions_by_tag_res_serialize((ta_find_transactions_by_tag_res_t*)res, json_result);
261304

@@ -284,11 +327,14 @@ status_t api_find_transactions_obj_by_tag(const iota_client_service_t* const ser
284327
goto done;
285328
}
286329

330+
lock_handle_lock(&cjson_lock);
287331
ret = ta_find_transactions_obj_by_tag(service, req, res);
288332
if (ret) {
333+
lock_handle_unlock(&cjson_lock);
289334
log_error(apis_logger_id, "[%s:%d]\n", __func__, __LINE__);
290335
goto done;
291336
}
337+
lock_handle_unlock(&cjson_lock);
292338

293339
ret = ta_find_transaction_objects_res_serialize(res, json_result);
294340

@@ -355,11 +401,14 @@ status_t api_mam_send_message(const iota_config_t* const tangle, const iota_clie
355401
ta_send_mam_req_t* req = send_mam_req_new();
356402
ta_send_mam_res_t* res = send_mam_res_new();
357403

404+
lock_handle_lock(&cjson_lock);
358405
if (send_mam_req_deserialize(payload, req)) {
406+
lock_handle_unlock(&cjson_lock);
359407
ret = SC_MAM_FAILED_INIT;
360408
log_error(apis_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_MAM_FAILED_INIT");
361409
goto done;
362410
}
411+
lock_handle_unlock(&cjson_lock);
363412

364413
// Creating MAM API
365414
prng = (req->prng[0]) ? req->prng : SEED;
@@ -404,11 +453,14 @@ status_t api_mam_send_message(const iota_config_t* const tangle, const iota_clie
404453
send_mam_res_set_channel_id(res, channel_id);
405454

406455
// Sending bundle
456+
lock_handle_lock(&cjson_lock);
407457
if (ta_send_bundle(tangle, service, bundle) != SC_OK) {
458+
lock_handle_unlock(&cjson_lock);
408459
ret = SC_MAM_FAILED_RESPONSE;
409460
log_error(apis_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_MAM_FAILED_RESPONSE");
410461
goto done;
411462
}
463+
lock_handle_unlock(&cjson_lock);
412464
send_mam_res_set_bundle_hash(res, transaction_bundle((iota_transaction_t*)utarray_front(bundle)));
413465

414466
ret = send_mam_res_serialize(res, json_result);
@@ -441,23 +493,30 @@ status_t api_send_transfer(const iota_config_t* const tangle, const iota_client_
441493
goto done;
442494
}
443495

496+
lock_handle_lock(&cjson_lock);
444497
ret = ta_send_transfer_req_deserialize(obj, req);
445498
if (ret) {
499+
lock_handle_unlock(&cjson_lock);
446500
goto done;
447501
}
448502

449503
ret = ta_send_transfer(tangle, service, req, res);
450504
if (ret) {
505+
lock_handle_unlock(&cjson_lock);
451506
goto done;
452507
}
508+
lock_handle_unlock(&cjson_lock);
453509

454510
// return transaction object
455511
hash243_queue_push(&txn_obj_req->hashes, hash243_queue_peek(res->hash));
456512

513+
lock_handle_lock(&cjson_lock);
457514
ret = ta_find_transaction_objects(service, txn_obj_req, res_txn_array);
458515
if (ret) {
516+
lock_handle_unlock(&cjson_lock);
459517
goto done;
460518
}
519+
lock_handle_unlock(&cjson_lock);
461520

462521
ret = ta_send_transfer_res_serialize(res_txn_array, json_result);
463522

@@ -480,15 +539,19 @@ status_t api_send_trytes(const iota_config_t* const tangle, const iota_client_se
480539
goto done;
481540
}
482541

542+
lock_handle_lock(&cjson_lock);
483543
ret = ta_send_trytes_req_deserialize(obj, trytes);
484544
if (ret != SC_OK) {
545+
lock_handle_unlock(&cjson_lock);
485546
goto done;
486547
}
487548

488549
ret = ta_send_trytes(tangle, service, trytes);
489550
if (ret != SC_OK) {
551+
lock_handle_unlock(&cjson_lock);
490552
goto done;
491553
}
554+
lock_handle_unlock(&cjson_lock);
492555

493556
ret = ta_send_trytes_res_serialize(trytes, json_result);
494557

accelerator/apis.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,24 @@ int apis_logger_release();
5858
status_t api_get_ta_info(char** json_result, ta_config_t* const info, iota_config_t* const tangle,
5959
ta_cache_t* const cache, iota_client_service_t* const service);
6060

61+
/**
62+
* Initialize lock
63+
*
64+
* @return
65+
* - zero on success
66+
* - SC_CONF_LOCK_INIT on error
67+
*/
68+
status_t apis_lock_init();
69+
70+
/**
71+
* Destroy lock
72+
*
73+
* @return
74+
* - zero on success
75+
* - SC_CONF_LOCK_DESTROY on error
76+
*/
77+
status_t apis_lock_destroy();
78+
6179
/**
6280
* @brief Generate an unused address.
6381
*

accelerator/errors.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ typedef enum {
152152
/**< No argument in CLI */
153153
SC_CONF_UNKNOWN_OPTION = 0x03 | SC_MODULE_CONF | SC_SEVERITY_FATAL,
154154
/**< undefined option in CLI */
155+
SC_CONF_LOCK_INIT = 0x04 | SC_MODULE_CONF | SC_SEVERITY_FATAL,
156+
/**< fail to init lock */
157+
SC_CONF_LOCK_DESTROY = 0x05 | SC_MODULE_CONF | SC_SEVERITY_FATAL,
158+
/**< fail to destroy lock */
155159

156160
// UTILS module
157161
SC_UTILS_NULL = 0x01 | SC_MODULE_UTILS | SC_SEVERITY_FATAL,

accelerator/main.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ int main(int argc, char* argv[]) {
4242
return EXIT_FAILURE;
4343
}
4444

45+
// Initialize apis cJSON lock
46+
if (apis_lock_init() != SC_OK) {
47+
log_critical(logger_id, "[%s:%d] Lock initialization failed %s.\n", __func__, __LINE__, MAIN_LOGGER);
48+
return EXIT_FAILURE;
49+
}
50+
4551
// Enable other loggers when verbose mode is on
4652
if (verbose_mode) {
4753
http_logger_init();
@@ -67,6 +73,11 @@ int main(int argc, char* argv[]) {
6773
}
6874

6975
cleanup:
76+
log_warning(logger_id, "Destroying API lock\n");
77+
if (apis_lock_destroy() != SC_OK) {
78+
log_critical(logger_id, "[%s:%d] Destroying api lock failed %s.\n", __func__, __LINE__, MAIN_LOGGER);
79+
return EXIT_FAILURE;
80+
}
7081
log_warning(logger_id, "Destroying TA configurations\n");
7182
ta_config_destroy(&ta_core.service);
7283

accelerator/server.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ int main(int argc, char* argv[]) {
8989
return EXIT_FAILURE;
9090
}
9191

92+
// Initialize apis cJSON lock
93+
if (apis_lock_init() != SC_OK) {
94+
log_critical(server_logger_id, "[%s:%d] Lock initialization failed %s.\n", __func__, __LINE__, SERVER_LOGGER);
95+
return EXIT_FAILURE;
96+
}
97+
9298
// Enable other loggers when verbose mode is on
9399
if (verbose_mode) {
94100
apis_logger_init();
@@ -417,6 +423,10 @@ int main(int argc, char* argv[]) {
417423
served::net::server server(ta_core.info.host, ta_core.info.port, mux);
418424
server.run(ta_core.info.thread_count);
419425

426+
if (apis_lock_destroy() != SC_OK) {
427+
log_critical(server_logger_id, "[%s:%d] Destroying api lock failed %s.\n", __func__, __LINE__, SERVER_LOGGER);
428+
return EXIT_FAILURE;
429+
}
420430
ta_config_destroy(&ta_core.service);
421431

422432
if (verbose_mode) {

0 commit comments

Comments
 (0)