diff --git a/c/opendht.cpp b/c/opendht.cpp index ba453c31b64a04c749d9b8342234b708d8114215..9cbfd2b5c6af6ec87f897309e823500ad589118d 100644 --- a/c/opendht.cpp +++ b/c/opendht.cpp @@ -206,11 +206,25 @@ void dht_runner_get(dht_runner* r, const dht_infohash* h, dht_get_cb cb, dht_don }); } -dht_op_token* dht_runner_listen(dht_runner* r, const dht_infohash* h, dht_value_cb cb, void* cb_user_data) { +struct ScopeGuardCb { + ScopeGuardCb(dht_shutdown_cb cb, void* data) + : onDestroy(cb), userData(data) {} + + ~ScopeGuardCb() { + if (onDestroy) + onDestroy((void*)userData); + } +private: + const dht_shutdown_cb onDestroy; + void const* userData; +}; + +dht_op_token* dht_runner_listen(dht_runner* r, const dht_infohash* h, dht_value_cb cb, dht_shutdown_cb done_cb, void* cb_user_data) { auto runner = reinterpret_cast<dht::DhtRunner*>(r); auto hash = reinterpret_cast<const dht::InfoHash*>(h); auto fret = new std::future<size_t>; - *fret = runner->listen(*hash, [cb,cb_user_data](const std::vector<std::shared_ptr<dht::Value>>& values, bool expired) { + auto guard = done_cb ? std::make_shared<ScopeGuardCb>(done_cb, cb_user_data) : std::shared_ptr<ScopeGuardCb>{}; + *fret = runner->listen(*hash, [cb,cb_user_data, guard](const std::vector<std::shared_ptr<dht::Value>>& values, bool expired) { for (const auto& value : values) { if (not cb(reinterpret_cast<const dht_value*>(&value), expired, cb_user_data)) return false; diff --git a/c/opendht_c.h b/c/opendht_c.h index ee3290fcd690527b342a96c1bba266f147635605..455d3d1bb7ebcfe6d71b14fa0e46dac0faca0176 100644 --- a/c/opendht_c.h +++ b/c/opendht_c.h @@ -127,7 +127,7 @@ OPENDHT_C_PUBLIC void dht_runner_run_config(dht_runner* runner, in_port_t port, OPENDHT_C_PUBLIC void dht_runner_ping(dht_runner* runner, struct sockaddr* addr, socklen_t addr_len); OPENDHT_C_PUBLIC void dht_runner_bootstrap(dht_runner* runner, const char* host, const char* service); OPENDHT_C_PUBLIC void dht_runner_get(dht_runner* runner, const dht_infohash* hash, dht_get_cb cb, dht_done_cb done_cb, void* cb_user_data); -OPENDHT_C_PUBLIC dht_op_token* dht_runner_listen(dht_runner* runner, const dht_infohash* hash, dht_value_cb cb, void* cb_user_data); +OPENDHT_C_PUBLIC dht_op_token* dht_runner_listen(dht_runner* runner, const dht_infohash* hash, dht_value_cb cb, dht_shutdown_cb done_cb, void* cb_user_data); OPENDHT_C_PUBLIC void dht_runner_cancel_listen(dht_runner* runner, const dht_infohash* hash, dht_op_token* token); OPENDHT_C_PUBLIC void dht_runner_put(dht_runner* runner, const dht_infohash* hash, const dht_value* value, dht_done_cb done_cb, void* cb_user_data); OPENDHT_C_PUBLIC void dht_runner_shutdown(dht_runner* runner, dht_shutdown_cb done_cb, void* cb_user_data); diff --git a/tools/dhtcnode.c b/tools/dhtcnode.c index 8ea9bb611911a0a3b0d27e53375f593c412d237a..99df250c0ad42b771009a5cfedf0ecd16d8afc09 100644 --- a/tools/dhtcnode.c +++ b/tools/dhtcnode.c @@ -44,7 +44,7 @@ int main() dht_runner_get(runner, &h, dht_get_callback, dht_done_callback, runner); // Listen for data - dht_op_token* token = dht_runner_listen(runner, &h, dht_value_callback, runner); + dht_op_token* token = dht_runner_listen(runner, &h, dht_value_callback, NULL, runner); sleep(1);