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

Commit

Permalink
feat: Pass proxy API directly
Browse files Browse the repository at this point in the history
We provide two way to process proxy API.
1. Pass request body to IRI directly.
2. Deserialize the request, then pass it to IRI.

This PR use the 1st solution which supports all the
IRI core API.

A user can choose which way they want with CLI argument
`--proxy_passthrough`
  • Loading branch information
howjmay committed Dec 27, 2019
1 parent 237cad1 commit 709d205
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 61 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,14 @@ clang-format can be installed by command:
* Proxy API to IRI core functionalities

### IRI Porxy API
`tangle-accelerator` allows the use of IRI core APIs. The calling process does not have to be aware of the destination machine running IRI. With the exactly same format of IRI API, `tangle-accelerator` would help user forward the request to IRI and forward the the response back to user. The followings are currently supporting Proxy APIs:
`tangle-accelerator` allows the use of IRI core APIs. The calling process does not have to be aware of the destination machine running IRI. With the exactly same format of IRI API, `tangle-accelerator` would help users forward the request to IRI and forward the response back to users.
We support two way to forward Proxy APIs to IRI:
1. Bypass Proxy APIs directly to IRI.
2. Process the Proxy APIs, then transmit them to IRI.

The user can choose which way they want with CLI argument `--proxy_passthrough`.
All the Proxy APIs are supported with the first way.
However, the second way currently only supports the followings Proxy APIs:
* checkConsistency
* findTransactions
* getBalances
Expand Down
2 changes: 1 addition & 1 deletion accelerator/common_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ static status_t ta_generate_address_thread(void* args) {
status_t ta_generate_address(const iota_config_t* const iconf, const iota_client_service_t* const service,
ta_generate_address_res_t* res) {
ta_generate_address_args_t args = {.iconf = iconf, .service = service, .res = res};
int *rval;
int* rval;
const struct itimerspec timeout = {.it_interval = {.tv_sec = 0, .tv_nsec = 0},
.it_value = {.tv_sec = 50, .tv_nsec = 0}};

Expand Down
14 changes: 11 additions & 3 deletions accelerator/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ struct option* cli_build_options() {
static status_t cli_core_set(char* conf_file, ta_config_t* const ta_conf, iota_config_t* const iota_conf,
ta_cache_t* const cache, iota_client_service_t* const iota_service,
db_client_service_t* const db_service, int key, char* const value) {
if (value == NULL || ta_conf == NULL || iota_conf == NULL || cache == NULL || iota_service == NULL ||
db_service == NULL) {
if (ta_conf == NULL || iota_conf == NULL || cache == NULL || iota_service == NULL || db_service == NULL) {
ta_log_error("%s\n", "SC_CONF_NULL");
return SC_CONF_NULL;
}
if (value == NULL && key != PROXY_API) {
ta_log_error("%s\n", "SC_CONF_NULL");
return SC_CONF_NULL;
}
Expand Down Expand Up @@ -95,6 +98,10 @@ static status_t cli_core_set(char* conf_file, ta_config_t* const ta_conf, iota_c
verbose_mode = (toupper(value[0]) == 'T');
break;

case PROXY_API:
ta_conf->proxy_passthrough = true;
break;

// File configuration
case CONF_CLI: {
size_t arg_len = strlen(value);
Expand Down Expand Up @@ -123,7 +130,8 @@ status_t ta_core_default_init(ta_config_t* const ta_conf, iota_config_t* const i
ta_conf->host = TA_HOST;
ta_conf->port = TA_PORT;
ta_conf->thread_count = TA_THREAD_COUNT;
#ifdef MQTT_ENABLE
ta_conf->proxy_passthrough = false;
#ifdef ENABLE_MQTT
ta_conf->mqtt_host = MQTT_HOST;
ta_conf->mqtt_topic_root = TOPIC_ROOT;
#endif
Expand Down
1 change: 1 addition & 0 deletions accelerator/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ typedef struct ta_config_s {
char* mqtt_host; /**< Address of MQTT broker host */
char* mqtt_topic_root; /**< The topic root of MQTT topic */
#endif
bool proxy_passthrough; /**< Pass proxy api directly without processing */
} ta_config_t;

/** struct type of iota configuration */
Expand Down
2 changes: 1 addition & 1 deletion accelerator/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ static inline int process_get_ta_info_request(ta_http_t *const http, char **cons

static inline int process_proxy_api_request(ta_http_t *const http, char const *const payload, char **const out) {
status_t ret;
ret = api_proxy_apis(&http->core->iota_service, payload, out);
ret = proxy_api_wrapper(&http->core->ta_conf, &http->core->iota_service, payload, out);
return set_response_content(ret, out);
}

Expand Down
2 changes: 2 additions & 0 deletions accelerator/message.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ typedef enum ta_cli_arg_value_e {
SEED_CLI,
CACHE,
CONF_CLI,
PROXY_API,

/** LOGGER */
VERBOSE,
Expand Down Expand Up @@ -68,6 +69,7 @@ static struct ta_cli_argument_s {
{"seed", SEED_CLI, "IOTA seed", OPTIONAL_ARG},
{"cache", CACHE, "Enable cache server with Y", REQUIRED_ARG},
{"config", CONF_CLI, "Read configuration file", REQUIRED_ARG},
{"proxy_passthrough", PROXY_API, "Pass proxy API directly to IRI without processing", NO_ARG},
{"verbose", VERBOSE, "Enable logger", NO_ARG}};

static const int cli_cmd_num = sizeof(ta_cli_arguments_g) / sizeof(struct ta_cli_argument_s);
Expand Down
104 changes: 62 additions & 42 deletions accelerator/proxy_apis.c
Original file line number Diff line number Diff line change
Expand Up @@ -322,50 +322,70 @@ static status_t api_get_trytes(const iota_client_service_t* const service, const
return ret;
}

status_t api_proxy_apis(const iota_client_service_t* const service, const char* const obj, char** json_result) {
status_t proxy_api_wrapper(const ta_config_t* const iconf, const iota_client_service_t* const service,
const char* const obj, char** json_result) {
status_t ret = SC_OK;
const uint8_t max_cmd_len = 30;
char command[max_cmd_len];

proxy_apis_command_req_deserialize(obj, command);
// TODO more proxy APIs should be implemented
enum {
H_checkConsistency = 3512812181U,
H_findTransactions = 1314581663U,
H_getBalances = 185959358U,
H_getInclusionStates = 3627925933U,
H_getNodeInfo = 1097192119U,
H_getTrytes = 3016694096U
};

// With DJB2 hash function we could reduce the amount of string comparisons and deterministic execution time
switch (hash_algo_djb2(command)) {
case H_checkConsistency:
ret = api_check_consistency(service, obj, json_result);
break;
case H_findTransactions:
ret = api_find_transactions(service, obj, json_result);
break;
case H_getBalances:
ret = api_get_balances(service, obj, json_result);
break;
case H_getInclusionStates:
ret = api_get_inclusion_states(service, obj, json_result);
break;
case H_getNodeInfo:
ret = api_get_node_info(service, json_result);
break;
case H_getTrytes:
ret = api_get_trytes(service, obj, json_result);
break;

default:
ta_log_error("%s\n", "SC_HTTP_URL_NOT_MATCH");
return SC_HTTP_URL_NOT_MATCH;
if (iconf->proxy_passthrough) {
char_buffer_t* res_buff = char_buffer_new();
char_buffer_t* req_buff = char_buffer_new();
char_buffer_set(req_buff, obj);

retcode_t result = iota_service_query(service, req_buff, res_buff);
if (result != RC_OK) {
ta_log_error("%s\n", error_2_string(result));
ret = SC_CCLIENT_FAILED_RESPONSE;
goto done;
}
char_buffer_to_str(res_buff, json_result);

done:
char_buffer_free(req_buff);
char_buffer_free(res_buff);
} else {
const uint8_t max_cmd_len = 30;
char command[max_cmd_len];

proxy_apis_command_req_deserialize(obj, command);
// TODO more proxy APIs should be implemented
enum {
H_checkConsistency = 3512812181U,
H_findTransactions = 1314581663U,
H_getBalances = 185959358U,
H_getInclusionStates = 3627925933U,
H_getNodeInfo = 1097192119U,
H_getTrytes = 3016694096U
};

// With DJB2 hash function we could reduce the amount of string comparisons and deterministic execution time
switch (hash_algo_djb2(command)) {
case H_checkConsistency:
ret = api_check_consistency(service, obj, json_result);
break;
case H_findTransactions:
ret = api_find_transactions(service, obj, json_result);
break;
case H_getBalances:
ret = api_get_balances(service, obj, json_result);
break;
case H_getInclusionStates:
ret = api_get_inclusion_states(service, obj, json_result);
break;
case H_getNodeInfo:
ret = api_get_node_info(service, json_result);
break;
case H_getTrytes:
ret = api_get_trytes(service, obj, json_result);
break;

default:
ta_log_error("%s\n", "SC_HTTP_URL_NOT_MATCH");
return SC_HTTP_URL_NOT_MATCH;
}

if (ret) {
ta_log_error("error code: %d\n", ret);
}
}

if (ret) {
ta_log_error("%d\n", ret);
}
return ret;
}
4 changes: 3 additions & 1 deletion accelerator/proxy_apis.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ status_t proxy_apis_lock_destroy();
/**
* @brief Proxy API of IOTA core functionalities
*
* @param[in] iconf IOTA API parameter configurations
* @param[in] service IRI node end point service
* @param[in] obj IOTA core APIs request body
* @param[out] json_result Result of IOTA core APIs
Expand All @@ -72,7 +73,8 @@ status_t proxy_apis_lock_destroy();
* - SC_OK on success
* - non-zero on error
*/
status_t api_proxy_apis(const iota_client_service_t* const service, const char* const obj, char** json_result);
status_t proxy_api_wrapper(const ta_config_t* const iconf, const iota_client_service_t* const service,
const char* const obj, char** json_result);

#ifdef __cplusplus
}
Expand Down
2 changes: 1 addition & 1 deletion accelerator/server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ int main(int argc, char* argv[]) {
res.set_status(SC_HTTP_BAD_REQUEST);
cJSON_Delete(json_obj);
} else {
ret = api_proxy_apis(&ta_core.iota_service, req.body().c_str(), &json_result);
ret = proxy_api_wrapper(&ta_core.ta_conf, &ta_core.iota_service, req.body().c_str(), &json_result);
ret = set_response_content(ret, &json_result);
res.set_status(ret);
}
Expand Down
3 changes: 2 additions & 1 deletion tests/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ void test_proxy_apis() {

for (size_t count = 0; count < TEST_COUNT; count++) {
test_time_start(&start_time);
TEST_ASSERT_EQUAL_INT32(SC_OK, api_proxy_apis(&ta_core.iota_service, proxy_apis_g[i].json, &json_result));
TEST_ASSERT_EQUAL_INT32(
SC_OK, proxy_api_wrapper(&ta_core.ta_conf, &ta_core.iota_service, proxy_apis_g[i].json, &json_result));
test_time_end(&start_time, &end_time, &sum);
free(json_result);
}
Expand Down
20 changes: 10 additions & 10 deletions tests/test_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,32 @@
#include "test_define.h"
#include "utils/timer.h"

int finite_thread(void *args) {
long x = *(int*)args;
pthread_exit((void *)x);
int finite_thread(void *args) {
long x = *(int *)args;
pthread_exit((void *)x);
}

int infinite_thread(void *args) {
long x = *(int*)args;
long x = *(int *)args;
while (1) {
// Cancellation point
pthread_testcancel();
}
pthread_exit((void*)x);
pthread_exit((void *)x);
}

void test_timer_finite(void) {
const struct itimerspec timeout = {.it_interval = {.tv_sec = 0, .tv_nsec = 0},
.it_value = {.tv_sec = 1, .tv_nsec = 0}};
int *args = (int*)malloc(sizeof(int));
int *args = (int *)malloc(sizeof(int));
TEST_ASSERT(args != NULL);
*args = 7;

ta_timer_t *timer_id = ta_timer_start(&timeout, finite_thread, args);
TEST_ASSERT(timer_id != NULL);

int *rval;
int ret = ta_timer_stop(timer_id, (void**)&rval);
int *rval;
int ret = ta_timer_stop(timer_id, (void **)&rval);
TEST_ASSERT(ret == SC_OK);
TEST_ASSERT((intptr_t)rval == *args);

Expand All @@ -45,15 +45,15 @@ void test_timer_finite(void) {
void test_timer_infinite(void) {
const struct itimerspec timeout = {.it_interval = {.tv_sec = 0, .tv_nsec = 0},
.it_value = {.tv_sec = 1, .tv_nsec = 0}};
int *args = (int*)malloc(sizeof(int));
int *args = (int *)malloc(sizeof(int));
TEST_ASSERT(args != NULL);
*args = 7;

ta_timer_t *timer_id = ta_timer_start(&timeout, infinite_thread, args);
TEST_ASSERT(timer_id != NULL);

int *rval;
int ret = ta_timer_stop(timer_id, (void**)&rval);
int ret = ta_timer_stop(timer_id, (void **)&rval);
TEST_ASSERT(ret == SC_UTILS_TIMER_EXPIRED);

free(args);
Expand Down

0 comments on commit 709d205

Please sign in to comment.