turn_transport: avoid leaking file descriptors

This patch fixes two issues in the shutdown function that were causing
file descriptors to remain open after they were no longer needed:
1) The TURN socket (`relay`) wasn't being destroyed properly
2) Several of the resources allocated in the TurnTransport constructor
   (such as the ioqueue and the timer_heap) weren't being cleaned up at
   all
The first issue was introduced in a recent commit (2569341fdf1d896e0e8).
The second one seems to have been present for a long time (at least over
a year).

Change-Id: I82e3f96b2a08737ce0a6e3ed5aaa53959de9b1e8
diff --git a/src/turn/turn_transport.cpp b/src/turn/turn_transport.cpp
index 49fdf59..0e36f46 100644
--- a/src/turn/turn_transport.cpp
+++ b/src/turn/turn_transport.cpp
@@ -84,17 +84,37 @@
         // otherwise there's a potential race condition where pj_turn_sock_destroy
         // sets the state of the TURN session to PJ_TURN_STATE_DESTROYING, and then
         // ioWorker tries to execute a callback which expects the session to be in
-        // an earlier state. (This causes a crash if PJSIP was compiled with asserts
-        // enabled, see https://git.jami.net/savoirfairelinux/jami-daemon/-/issues/974)
+        // an earlier state. See https://git.jami.net/savoirfairelinux/dhtnet/-/issues/27
         if (ioWorker.joinable()) {
             stopped_ = true;
             ioWorker.join();
         }
         if (relay) {
             pj_turn_sock_destroy(relay);
+            // Calling pj_turn_sock_destroy doesn't (necessarily) immediately close the
+            // socket; as mentioned in PJSIP's documentation, the operation may be performed
+            // asynchronously, which is why we need to call the two polling functions below.
+            // https://docs.pjsip.org/en/latest/api/generated/pjnath/group/group__PJNATH__TURN__SOCK.html
+            const pj_time_val delay = {0, 20};
+            pj_ioqueue_poll(stunConfig.ioqueue, &delay);
+            pj_timer_heap_poll(stunConfig.timer_heap, nullptr);
             relay = nullptr;
         }
         turnLock.reset();
+        if (stunConfig.timer_heap) {
+            pj_timer_heap_destroy(stunConfig.timer_heap);
+            stunConfig.timer_heap = nullptr;
+        }
+        if (stunConfig.ioqueue) {
+            pj_ioqueue_destroy(stunConfig.ioqueue);
+            stunConfig.ioqueue = nullptr;
+        }
+        if (pool) {
+            pj_pool_release(pool);
+            pool = nullptr;
+        }
+        pj_pool_factory_dump(&poolCache.factory, PJ_TRUE);
+        pj_caching_pool_destroy(&poolCache);
     }
 
     TurnTransportParams settings;
@@ -119,7 +139,6 @@
 TurnTransport::Impl::~Impl()
 {
     shutdown();
-    pj_caching_pool_destroy(&poolCache);
 }
 
 void