From b680407e9ae995e0f25cada566bd21ca59c2f662 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com>
Date: Mon, 21 Oct 2019 11:08:42 -0400
Subject: [PATCH] c wrapper: add callback to free listen context data

---
 c/opendht.cpp    | 18 ++++++++++++++++--
 c/opendht_c.h    |  2 +-
 tools/dhtcnode.c |  2 +-
 3 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/c/opendht.cpp b/c/opendht.cpp
index ba453c31..9cbfd2b5 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 ee3290fc..455d3d1b 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 8ea9bb61..99df250c 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);
 
-- 
GitLab