diff --git a/include/in3/client.h b/include/in3/client.h index 0ef39a726..4fa1144eb 100644 --- a/include/in3/client.h +++ b/include/in3/client.h @@ -250,13 +250,21 @@ typedef void (*in3_storage_set_item)( bytes_t* value /**< the value to store.*/ ); +/** + * storage handler function for clearing the cache. + **/ +typedef void (*in3_storage_clear)( + void* cptr /**< a custom pointer as set in the storage handler*/ +); + /** * storage handler to handle cache. **/ typedef struct in3_storage_handler { in3_storage_get_item get_item; /**< function pointer returning a stored value for the given key.*/ in3_storage_set_item set_item; /**< function pointer setting a stored value for the given key.*/ - void* cptr; /**< custom pointer which will will be passed to functions */ + in3_storage_clear clear; /**< function pointer clearing all contents of cache.*/ + void* cptr; /**< custom pointer which will be passed to functions */ } in3_storage_handler_t; #define IN3_SIGN_ERR_REJECTED -1 /**< return value used by the signer if the the signature-request was rejected. */ @@ -462,6 +470,7 @@ typedef struct in3_t_ { * in3_storage_handler_t storage_handler; * storage_handler.get_item = storage_get_item; * storage_handler.set_item = storage_set_item; + * storage_handler.clear = storage_clear; * * // configure transport * client->transport = send_curl; @@ -499,6 +508,7 @@ in3_t* in3_new() __attribute__((deprecated("use in3_for_chain(ETH_CHAIN_ID_MULTI * in3_storage_handler_t storage_handler; * storage_handler.get_item = storage_get_item; * storage_handler.set_item = storage_set_item; + * storage_handler.clear = storage_clear; * * // configure transport * client->transport = send_curl; @@ -644,9 +654,10 @@ in3_signer_t* in3_create_signer( * create a new storage handler-object to be set on the client. * the caller will need to free this pointer after usage. */ -in3_storage_handler_t* in3_create_storeage_handler( +in3_storage_handler_t* in3_create_storage_handler( in3_storage_get_item get_item, /**< function pointer returning a stored value for the given key.*/ in3_storage_set_item set_item, /**< function pointer setting a stored value for the given key.*/ + in3_storage_clear clear, /**< function pointer clearing all contents of cache.*/ void* cptr /**< custom pointer which will will be passed to functions */ ); #endif diff --git a/src/api/eth1/rpc_api.c b/src/api/eth1/rpc_api.c index 0394f8237..82542ffba 100644 --- a/src/api/eth1/rpc_api.c +++ b/src/api/eth1/rpc_api.c @@ -139,6 +139,17 @@ static in3_ret_t in3_config(in3_ctx_t* ctx, d_token_t* params, in3_response_t** return IN3_OK; } +static in3_ret_t in3_cacheClear(in3_ctx_t* ctx, in3_response_t** response) { + in3_storage_handler_t* cache = ctx->client->cache; + if (!cache || !cache->clear) + return ctx_set_error(ctx, "No storage set", IN3_ECONFIG); + cache->clear(cache->cptr); + RESPONSE_START(); + sb_add_chars(&response[0]->result, "true"); + RESPONSE_END(); + return IN3_OK; +} + static in3_ret_t eth_handle_intern(in3_ctx_t* ctx, in3_response_t** response) { if (ctx->len > 1) return IN3_ENOTSUP; // internal handling is only possible for single requests (at least for now) d_token_t* r = ctx->requests[0]; @@ -150,6 +161,7 @@ static in3_ret_t eth_handle_intern(in3_ctx_t* ctx, in3_response_t** response) { if (strcmp(method, "in3_checksumAddress") == 0) return in3_checkSumAddress(ctx, params, response); if (strcmp(method, "web3_sha3") == 0) return in3_sha3(ctx, params, response); if (strcmp(method, "in3_config") == 0) return in3_config(ctx, params, response); + if (strcmp(method, "in3_cacheClear") == 0) return in3_cacheClear(ctx, response); return parent_handle ? parent_handle(ctx, response) : IN3_OK; } @@ -162,7 +174,8 @@ static int verify(in3_vctx_t* v) { strcmp(method, "in3_abiDecode") == 0 || strcmp(method, "in3_checksumAddress") == 0 || strcmp(method, "web3_sha3") == 0 || - strcmp(method, "in3_config") == 0) + strcmp(method, "in3_config") == 0 || + strcmp(method, "in3_cacheClear") == 0) return IN3_OK; return parent_verify ? parent_verify(v) : IN3_ENOTSUP; diff --git a/src/cmd/in3/CMakeLists.txt b/src/cmd/in3/CMakeLists.txt index 86338f6f0..0a0fb45b3 100644 --- a/src/cmd/in3/CMakeLists.txt +++ b/src/cmd/in3/CMakeLists.txt @@ -50,7 +50,7 @@ ENDIF() add_executable(in3 main.c in3_storage.c) - +target_compile_definitions(in3 PRIVATE _XOPEN_SOURCE=600) target_link_libraries(in3 ${LIBS} eth_full eth_api -lm) install(TARGETS in3 diff --git a/src/cmd/in3/in3_storage.c b/src/cmd/in3/in3_storage.c index fcc0508c2..6f7d53b99 100644 --- a/src/cmd/in3/in3_storage.c +++ b/src/cmd/in3/in3_storage.c @@ -33,15 +33,19 @@ * with this program. If not, see . *******************************************************************************/ +#include "in3_storage.h" #include "../../core/client/client.h" #include "../../core/util/mem.h" + #include #include #include #if defined(_WIN32) #include +#include #else +#include #include #include #endif @@ -113,3 +117,49 @@ void storage_set_item(void* cptr, char* key, bytes_t* content) { } _free(path); } + +#if defined(_WIN32) +static void rm_recurs(const char* path) { + struct dirent* entry = NULL; + DIR* dir = NULL; + dir = opendir(path); + while ((entry = readdir(dir))) { + DIR* sub_dir = NULL; + FILE* file = NULL; + char abs_path[270] = {0}; + if (*(entry->d_name) != '.') { + sprintf(abs_path, "%s/%s", path, entry->d_name); + if ((sub_dir = opendir(abs_path))) { + closedir(sub_dir); + rm_recurs(abs_path); + } else { + if ((file = fopen(abs_path, "r"))) { + fclose(file); + remove(abs_path); + } + } + } + } + remove(path); +} +#else +static int unlink_cb(const char* fpath, const struct stat* sb, int typeflag, struct FTW *ftwbuf) { + UNUSED_VAR(sb); + UNUSED_VAR(typeflag); + UNUSED_VAR(ftwbuf); + return remove(fpath); +} + +static void rm_recurs(const char* dir) { + nftw(dir, unlink_cb, 64, FTW_DEPTH | FTW_PHYS); +} +#endif + +void storage_clear(void* cptr) { + UNUSED_VAR(cptr); + rm_recurs(get_storage_dir()); + // recreate storage dir + free(_HOME_DIR); + _HOME_DIR = NULL; + get_storage_dir(); +} diff --git a/src/cmd/in3/in3_storage.h b/src/cmd/in3/in3_storage.h index 633b52ba6..ecabc6f64 100644 --- a/src/cmd/in3/in3_storage.h +++ b/src/cmd/in3/in3_storage.h @@ -40,4 +40,6 @@ bytes_t* storage_get_item(void* cptr, char* key); -void storage_set_item(void* cptr, char* key, bytes_t* content); \ No newline at end of file +void storage_set_item(void* cptr, char* key, bytes_t* content); + +void storage_clear(void* cptr); \ No newline at end of file diff --git a/src/cmd/in3/main.c b/src/cmd/in3/main.c index 64d75d15e..ebc01ab19 100644 --- a/src/cmd/in3/main.c +++ b/src/cmd/in3/main.c @@ -556,6 +556,7 @@ int main(int argc, char* argv[]) { in3_storage_handler_t storage_handler; storage_handler.get_item = storage_get_item; storage_handler.set_item = storage_set_item; + storage_handler.clear = storage_clear; // we want to verify all in3_register_eth_full(); @@ -609,6 +610,8 @@ int main(int argc, char* argv[]) { pk_file = argv[++i]; } else if (strcmp(argv[i], "-chain") == 0 || strcmp(argv[i], "-c") == 0) // chain_id set_chain_id(c, argv[++i]); + else if (strcmp(argv[i], "-ccache") == 0) // clear cache + c->cache->clear(c->cache->cptr); else if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "-data") == 0) { // data char* d = argv[++i]; if (strcmp(d, "-") == 0) @@ -825,7 +828,7 @@ int main(int argc, char* argv[]) { return 0; } else if (strcmp(method, "autocompletelist") == 0) { - printf("send call abi_encode abi_decode ecrecover key -sigtype -st eth_sign raw hash sign createkey -ri -ro keystore unlock pk2address pk2public mainnet tobalaba kovan goerli local volta true false latest -np -debug -c -chain -p -version -proof -s -signs -b -block -to -d -data -gas_limit -value -w -wait -hex -json in3_nodeList in3_stats in3_sign web3_clientVersion web3_sha3 net_version net_peerCount net_listening eth_protocolVersion eth_syncing eth_coinbase eth_mining eth_hashrate eth_gasPrice eth_accounts eth_blockNumber eth_getBalance eth_getStorageAt eth_getTransactionCount eth_getBlockTransactionCountByHash eth_getBlockTransactionCountByNumber eth_getUncleCountByBlockHash eth_getUncleCountByBlockNumber eth_getCode eth_sign eth_sendTransaction eth_sendRawTransaction eth_call eth_estimateGas eth_getBlockByHash eth_getBlockByNumber eth_getTransactionByHash eth_getTransactionByBlockHashAndIndex eth_getTransactionByBlockNumberAndIndex eth_getTransactionReceipt eth_pendingTransactions eth_getUncleByBlockHashAndIndex eth_getUncleByBlockNumberAndIndex eth_getCompilers eth_compileLLL eth_compileSolidity eth_compileSerpent eth_newFilter eth_newBlockFilter eth_newPendingTransactionFilter eth_uninstallFilter eth_getFilterChanges eth_getFilterLogs eth_getLogs eth_getWork eth_submitWork eth_submitHashrate\n"); + printf("send call abi_encode abi_decode ecrecover key -sigtype -st eth_sign raw hash sign createkey -ri -ro keystore unlock pk2address pk2public mainnet tobalaba kovan goerli local volta true false latest -np -debug -c -chain -p -version -proof -s -signs -b -block -to -d -data -gas_limit -value -w -wait -hex -json in3_nodeList in3_stats in3_sign web3_clientVersion web3_sha3 net_version net_peerCount net_listening eth_protocolVersion eth_syncing eth_coinbase eth_mining eth_hashrate eth_gasPrice eth_accounts eth_blockNumber eth_getBalance eth_getStorageAt eth_getTransactionCount eth_getBlockTransactionCountByHash eth_getBlockTransactionCountByNumber eth_getUncleCountByBlockHash eth_getUncleCountByBlockNumber eth_getCode eth_sign eth_sendTransaction eth_sendRawTransaction eth_call eth_estimateGas eth_getBlockByHash eth_getBlockByNumber eth_getTransactionByHash eth_getTransactionByBlockHashAndIndex eth_getTransactionByBlockNumberAndIndex eth_getTransactionReceipt eth_pendingTransactions eth_getUncleByBlockHashAndIndex eth_getUncleByBlockNumberAndIndex eth_getCompilers eth_compileLLL eth_compileSolidity eth_compileSerpent eth_newFilter eth_newBlockFilter eth_newPendingTransactionFilter eth_uninstallFilter eth_getFilterChanges eth_getFilterLogs eth_getLogs eth_getWork eth_submitWork eth_submitHashrate in3_cacheClear\n"); return 0; } else if (strcmp(method, "createkey") == 0) { time_t t; diff --git a/src/core/client/client.c b/src/core/client/client.c index b16e7b4b3..fb5a0a208 100644 --- a/src/core/client/client.c +++ b/src/core/client/client.c @@ -200,14 +200,16 @@ in3_signer_t* in3_create_signer( return signer; } -in3_storage_handler_t* in3_create_storeage_handler( +in3_storage_handler_t* in3_create_storage_handler( in3_storage_get_item get_item, /**< function pointer returning a stored value for the given key.*/ in3_storage_set_item set_item, /**< function pointer setting a stored value for the given key.*/ + in3_storage_clear clear, /**< function pointer setting a stored value for the given key.*/ void* cptr /**< custom pointer which will will be passed to functions */ ) { in3_storage_handler_t* handler = _calloc(1, sizeof(in3_storage_handler_t)); handler->cptr = cptr; handler->get_item = get_item; handler->set_item = set_item; + handler->clear = clear; return handler; } diff --git a/src/core/client/client.h b/src/core/client/client.h index 5f2dc7d5e..181bba0f0 100644 --- a/src/core/client/client.h +++ b/src/core/client/client.h @@ -250,13 +250,21 @@ typedef void (*in3_storage_set_item)( bytes_t* value /**< the value to store.*/ ); +/** + * storage handler function for clearing the cache. + **/ +typedef void (*in3_storage_clear)( + void* cptr /**< a custom pointer as set in the storage handler*/ +); + /** * storage handler to handle cache. **/ typedef struct in3_storage_handler { in3_storage_get_item get_item; /**< function pointer returning a stored value for the given key.*/ in3_storage_set_item set_item; /**< function pointer setting a stored value for the given key.*/ - void* cptr; /**< custom pointer which will will be passed to functions */ + in3_storage_clear clear; /**< function pointer clearing all contents of cache.*/ + void* cptr; /**< custom pointer which will be passed to functions */ } in3_storage_handler_t; #define IN3_SIGN_ERR_REJECTED -1 /**< return value used by the signer if the the signature-request was rejected. */ @@ -462,6 +470,7 @@ typedef struct in3_t_ { * in3_storage_handler_t storage_handler; * storage_handler.get_item = storage_get_item; * storage_handler.set_item = storage_set_item; + * storage_handler.clear = storage_clear; * * // configure transport * client->transport = send_curl; @@ -499,6 +508,7 @@ in3_t* in3_new() __attribute__((deprecated("use in3_for_chain(ETH_CHAIN_ID_MULTI * in3_storage_handler_t storage_handler; * storage_handler.get_item = storage_get_item; * storage_handler.set_item = storage_set_item; + * storage_handler.clear = storage_clear; * * // configure transport * client->transport = send_curl; @@ -644,9 +654,10 @@ in3_signer_t* in3_create_signer( * create a new storage handler-object to be set on the client. * the caller will need to free this pointer after usage. */ -in3_storage_handler_t* in3_create_storeage_handler( +in3_storage_handler_t* in3_create_storage_handler( in3_storage_get_item get_item, /**< function pointer returning a stored value for the given key.*/ in3_storage_set_item set_item, /**< function pointer setting a stored value for the given key.*/ + in3_storage_clear clear, /**< function pointer clearing all contents of cache.*/ void* cptr /**< custom pointer which will will be passed to functions */ ); #endif diff --git a/test/unit_tests/test_request.c b/test/unit_tests/test_request.c index 652373ec0..f914bd2ae 100644 --- a/test/unit_tests/test_request.c +++ b/test/unit_tests/test_request.c @@ -90,7 +90,7 @@ void test_exec_req() { in3_register_eth_api(); in3_t* c = in3_for_chain(ETH_CHAIN_ID_MAINNET); - ; + char* result = in3_client_exec_req(c, "{\"method\":\"web3_sha3\",\"params\":[\"0x1234\"]}"); TEST_ASSERT_EQUAL_STRING("{\"id\":1,\"jsonrpc\":\"2.0\",\"result\":\"0x56570de287d73cd1cb6092bb8fdee6173974955fdef345ae579ee9f475ea7432\"}", result); _free(result); @@ -103,6 +103,10 @@ void test_exec_req() { TEST_ASSERT_EQUAL_STRING("{\"id\":0,\"jsonrpc\":\"2.0\",\"error\":{\"code\":-6,\"message\":\"No Method defined\"}}", result); _free(result); + result = in3_client_exec_req(c, "{\"method\":\"in3_cacheClear\",\"params\":[]}"); + TEST_ASSERT_EQUAL_STRING("{\"id\":0,\"jsonrpc\":\"2.0\",\"error\":{\"code\":-6,\"message\":\"The request could not be handled\nNo storage set\"}}", result); + _free(result); + in3_free(c); } /* @@ -110,7 +114,7 @@ void test_exec_req() { */ int main() { _free(in3_create_signer(NULL, NULL, NULL)); - _free(in3_create_storeage_handler(NULL, NULL, NULL)); + _free(in3_create_storage_handler(NULL, NULL, NULL, NULL)); TESTS_BEGIN(); RUN_TEST(test_configure_request);