@@ -69,11 +69,12 @@ typedef struct loader_impl_rpc_handle_type
6969
7070typedef struct loader_impl_rpc_function_type
7171{
72- loader_impl_rpc_function_type (loader_impl_rpc rpc_impl, const std::string &url, bool is_async, const std::string &func_name) :
73- rpc_impl (rpc_impl), url(url + (is_async ? " await/" : " call/" ) + func_name) {}
72+ loader_impl_rpc_function_type (loader_impl_rpc rpc_impl, const std::string &url, bool is_async, const std::string &func_name, const int &timeout ) :
73+ rpc_impl (rpc_impl), url(url + (is_async ? " await/" : " call/" ) + func_name), timeout(timeout) {}
7474
7575 loader_impl_rpc rpc_impl;
7676 std::string url;
77+ int timeout;
7778
7879} * loader_impl_rpc_function;
7980
@@ -95,7 +96,7 @@ struct rpc_async_context
9596};
9697
9798static size_t rpc_loader_impl_write_data (void *buffer, size_t size, size_t nmemb, void *userp);
98- static int rpc_loader_impl_discover_value (loader_impl_rpc rpc_impl, const std::string &url, value v, context ctx);
99+ static int rpc_loader_impl_discover_value (loader_impl_rpc rpc_impl, const std::string &url, value v, context ctx, const int &timeout );
99100static int rpc_loader_impl_initialize_types (loader_impl impl, loader_impl_rpc rpc_impl);
100101
101102size_t rpc_loader_impl_write_data (void *buffer, size_t size, size_t nmemb, void *userp)
@@ -203,6 +204,7 @@ function_return function_rpc_interface_invoke(function func, function_impl impl,
203204 curl_easy_setopt (easy, CURLOPT_POSTFIELDS , buffer);
204205 curl_easy_setopt (easy, CURLOPT_POSTFIELDSIZE , body_request_size - 1 );
205206 curl_easy_setopt (easy, CURLOPT_WRITEDATA , static_cast <loader_impl_rpc_write_data>(&write_data));
207+ curl_easy_setopt (easy, CURLOPT_TIMEOUT_MS , rpc_function->timeout );
206208
207209 CURLcode res;
208210
@@ -423,6 +425,7 @@ function_return function_rpc_interface_await(function func, function_impl impl,
423425 curl_easy_setopt (easy, CURLOPT_WRITEFUNCTION , rpc_loader_impl_write_data);
424426 curl_easy_setopt (easy, CURLOPT_WRITEDATA , static_cast <loader_impl_rpc_write_data>(&async_ctx->write_data ));
425427 curl_easy_setopt (easy, CURLOPT_PRIVATE , async_ctx);
428+ curl_easy_setopt (easy, CURLOPT_TIMEOUT_MS , rpc_function->timeout );
426429
427430 /* COPYPOSTFIELDS copies data internally, safe to free buffer after */
428431 curl_easy_setopt (easy, CURLOPT_POSTFIELDSIZE , (long )(body_request_size - 1 ));
@@ -744,7 +747,7 @@ int rpc_loader_impl_clear(loader_impl impl, loader_handle handle)
744747 return 0 ;
745748}
746749
747- int rpc_loader_impl_discover_value (loader_impl_rpc rpc_impl, const std::string &url, void *v, context ctx)
750+ int rpc_loader_impl_discover_value (loader_impl_rpc rpc_impl, const std::string &url, void *v, context ctx, const int &timeout )
748751{
749752 metacall::map_typed<std::string, metacall::array> inspect (v);
750753
@@ -763,7 +766,7 @@ int rpc_loader_impl_discover_value(loader_impl_rpc rpc_impl, const std::string &
763766 const auto &signature_map = func_map[" signature" ].as <metacall::map_typed<std::string, metacall::value>>();
764767 const auto &args = signature_map[" args" ].as <metacall::array>();
765768
766- loader_impl_rpc_function rpc_func = new loader_impl_rpc_function_type (rpc_impl, url, is_async, func_name);
769+ loader_impl_rpc_function rpc_func = new loader_impl_rpc_function_type (rpc_impl, url, is_async, func_name, timeout );
767770
768771 function f = function_create (func_name.c_str (), args.size (), rpc_func, &function_rpc_singleton);
769772 signature s = function_signature (f);
@@ -810,26 +813,33 @@ int rpc_loader_impl_discover(loader_impl impl, loader_handle handle, context ctx
810813
811814 for (const auto &config : rpc_handle->configs )
812815 {
813- auto urls = config[" urls" ].as <metacall::array>();
814- // TODO:
815- // auto timeout = config["timeout"].as<int>();
816- // auto retry = config["retry"].as<int>();
816+ const auto urls = config[" urls" ].as <metacall::array>();
817+ const auto timeout = config[" timeout" ].as <int >();
818+ const auto retry = config[" retry" ].as <int >();
817819
818820 for (const auto &url : urls)
819821 {
820822 loader_impl_rpc_write_data_type write_data;
821823 const auto &url_str = url.as <std::string>();
822824 std::string base_url = url_str.back () != ' /' ? url_str + ' /' : url_str;
823825 std::string inspect_url = base_url + " inspect" ;
826+ int retry_count = 0 ;
824827 CURLcode res;
825828
826- curl_easy_setopt (rpc_impl->discover_curl , CURLOPT_URL , inspect_url.c_str ());
827- curl_easy_setopt (rpc_impl->discover_curl , CURLOPT_WRITEDATA , static_cast <loader_impl_rpc_write_data>(&write_data));
829+ do
830+ {
831+ curl_easy_setopt (rpc_impl->discover_curl , CURLOPT_URL , inspect_url.c_str ());
832+ curl_easy_setopt (rpc_impl->discover_curl , CURLOPT_WRITEDATA , static_cast <loader_impl_rpc_write_data>(&write_data));
833+ curl_easy_setopt (rpc_impl->discover_curl , CURLOPT_TIMEOUT_MS , timeout);
834+
835+ log_write (" metacall" , metacall::detail::LOG_LEVEL_DEBUG , " Trying to connect to %s retry %d/%d with timeout %d" , inspect_url.c_str (), retry_count + 1 , retry, timeout);
836+
837+ /* Skip curl_multi_perform use-of-uninitialized-value from heap allocation of curl_mvaprintf in uninstrumented libcurl */
838+ memory_sanitizer_uninstrumented ({
839+ res = curl_easy_perform (rpc_impl->discover_curl );
840+ });
828841
829- /* Skip curl_multi_perform use-of-uninitialized-value from heap allocation of curl_mvaprintf in uninstrumented libcurl */
830- memory_sanitizer_uninstrumented ({
831- res = curl_easy_perform (rpc_impl->discover_curl );
832- });
842+ } while (retry_count++ < retry && res != CURLE_OK );
833843
834844 if (res != CURLE_OK )
835845 {
@@ -849,7 +859,7 @@ int rpc_loader_impl_discover(loader_impl impl, loader_handle handle, context ctx
849859 }
850860
851861 /* Discover the functions from the inspect value */
852- if (rpc_loader_impl_discover_value (rpc_impl, base_url, inspect_value, ctx) != 0 )
862+ if (rpc_loader_impl_discover_value (rpc_impl, base_url, inspect_value, ctx, timeout ) != 0 )
853863 {
854864 log_write (" metacall" , metacall::detail::LOG_LEVEL_ERROR , " Invalid inspect value discover from API endpoint %s" , url_str.c_str ());
855865 return 1 ;
0 commit comments