make upnp take asio context

Change-Id: Ie039a084d04dee1a1bfcda5865b6482f272ccfe3
diff --git a/include/ice_options.h b/include/ice_options.h
index c26b83e..e7aee6d 100644
--- a/include/ice_options.h
+++ b/include/ice_options.h
@@ -8,6 +8,10 @@
 
 namespace jami {
 
+namespace upnp {
+class UPnPContext;
+}
+
 class IceTransportFactory;
 using IceTransportCompleteCb = std::function<void(bool)>;
 
@@ -61,6 +65,7 @@
     // Addresses used by the account owning the transport instance.
     IpAddr accountLocalAddr {};
     IpAddr accountPublicAddr {};
+    std::shared_ptr<upnp::UPnPContext> upnpContext {};
 };
 
 }
diff --git a/include/upnp/upnp_context.h b/include/upnp/upnp_context.h
index a85db51..b9a5d26 100644
--- a/include/upnp/upnp_context.h
+++ b/include/upnp/upnp_context.h
@@ -37,6 +37,7 @@
 #include "upnp/mapping.h"
 
 #include <opendht/rng.h>
+#include <opendht/logger.h>
 #include <asio/steady_timer.hpp>
 
 #include <set>
@@ -110,11 +111,11 @@
     };
 
 public:
-    UPnPContext();
+    UPnPContext(std::shared_ptr<asio::io_context> ctx, std::shared_ptr<dht::log::Logger> logger);
     ~UPnPContext();
 
     // Retrieve the UPnPContext singleton.
-    static std::shared_ptr<UPnPContext> getUPnPContext();
+    // static std::shared_ptr<UPnPContext> getUPnPContext();
 
     // Terminate the instance.
     void shutdown();
diff --git a/include/upnp/upnp_control.h b/include/upnp/upnp_control.h
index 10e44e3..e68cada 100644
--- a/include/upnp/upnp_control.h
+++ b/include/upnp/upnp_control.h
@@ -40,7 +40,7 @@
 class Controller
 {
 public:
-    Controller();
+    Controller(const std::shared_ptr<UPnPContext>& ctx);
     ~Controller();
 
     // Set known public address
diff --git a/include/upnp/upnp_thread_util.h b/include/upnp/upnp_thread_util.h
index 6c7f97b..6bc5271 100644
--- a/include/upnp/upnp_thread_util.h
+++ b/include/upnp/upnp_thread_util.h
@@ -3,12 +3,13 @@
 #include <thread>
 #include <memory>
 #include <asio/io_context.hpp>
+#include <fmt/format.h>
 
 // This macro is used to validate that a code is executed from the expected
 // thread. It's useful to detect unexpected race on data members.
 #define CHECK_VALID_THREAD() \
     if (not isValidThread()) \
-        printf("The calling thread %d is not the expected thread: %d", getCurrentThread(), threadId_);
+        fmt::print("The calling thread {} is not the expected thread: {}\n", getCurrentThread(), threadId_);
         /*JAMI_ERR() << "The calling thread " << getCurrentThread() \
                    << " is not the expected thread: " << threadId_;*/
 
diff --git a/src/ice_transport.cpp b/src/ice_transport.cpp
index 1b8ef83..ff0b51f 100644
--- a/src/ice_transport.cpp
+++ b/src/ice_transport.cpp
@@ -422,7 +422,7 @@
              initiatorSession_ ? "master" : "slave");
 
     if (upnpEnabled_)
-        upnp_.reset(new upnp::Controller());
+        upnp_.reset(new upnp::Controller(options.upnpContext));
 
     config_ = options.factory->getIceCfg(); // config copy
     if (isTcp_) {
diff --git a/src/upnp/protocol/upnp_protocol.h b/src/upnp/protocol/upnp_protocol.h
index 8ce0820..048f385 100644
--- a/src/upnp/protocol/upnp_protocol.h
+++ b/src/upnp/protocol/upnp_protocol.h
@@ -22,7 +22,7 @@
 #pragma once
 
 #include "igd.h"
-#include "mapping.h"
+#include "upnp/mapping.h"
 #include "ip_utils.h"
 
 #include <map>
diff --git a/src/upnp/upnp_context.cpp b/src/upnp/upnp_context.cpp
index 11112b7..a36e56f 100644
--- a/src/upnp/upnp_context.cpp
+++ b/src/upnp/upnp_context.cpp
@@ -21,7 +21,10 @@
  */
 
 #include "upnp/upnp_context.h"
+#include "protocol/upnp_protocol.h"
+
 #include <asio/steady_timer.hpp>
+#include <fmt/std.h>
 
 namespace jami {
 namespace upnp {
@@ -35,7 +38,8 @@
 constexpr static uint16_t UPNP_UDP_PORT_MIN {20000};
 constexpr static uint16_t UPNP_UDP_PORT_MAX {UPNP_UDP_PORT_MIN + 5000};
 
-UPnPContext::UPnPContext()
+UPnPContext::UPnPContext(std::shared_ptr<asio::io_context> ctx, std::shared_ptr<dht::log::Logger> logger)
+ : mappingListUpdateTimer_(*ioContext)
 {
     // JAMI_DBG("Creating UPnPContext instance [%p]", this);
 
@@ -43,19 +47,16 @@
     portRange_.emplace(PortType::TCP, std::make_pair(UPNP_TCP_PORT_MIN, UPNP_TCP_PORT_MAX));
     portRange_.emplace(PortType::UDP, std::make_pair(UPNP_UDP_PORT_MIN, UPNP_UDP_PORT_MAX));
 
-    if (not isValidThread()) {
-        runOnUpnpContextQueue([this] { init(); });
-        return;
-    }
+    ioContext->post([this] { init(); });
 }
 
-std::shared_ptr<UPnPContext>
+/*std::shared_ptr<UPnPContext>
 UPnPContext::getUPnPContext()
 {
     // This is the unique shared instance (singleton) of UPnPContext class.
     static auto context = std::make_shared<UPnPContext>();
     return context;
-}
+}*/
 
 void
 UPnPContext::shutdown(std::condition_variable& cv)
@@ -71,8 +72,9 @@
     {
         std::lock_guard<std::mutex> lock(mappingMutex_);
         mappingList_->clear();
-        if (mappingListUpdateTimer_)
-            mappingListUpdateTimer_->cancel();
+        //if (mappingListUpdateTimer_)
+        //    mappingListUpdateTimer_->cancel();
+        mappingListUpdateTimer_.cancel();
         controllerList_.clear();
         protocolList_.clear();
         shutdownComplete_ = true;
@@ -310,7 +312,7 @@
 
     if (desiredPort == 0) {
         // JAMI_DBG("Desired port is not set, will provide the first available port for [%s]",
-                 requestedMap.getTypeStr());
+        //         requestedMap.getTypeStr());
     } else {
         // JAMI_DBG("Try to find mapping for port %i [%s]", desiredPort, requestedMap.getTypeStr());
     }
@@ -613,10 +615,11 @@
     // Update the preferred IGD.
     updatePreferredIgd();
 
-    if (mappingListUpdateTimer_) {
+    /*if (mappingListUpdateTimer_) {
         mappingListUpdateTimer_->cancel();
         mappingListUpdateTimer_ = {};
-    }
+    }*/
+    mappingListUpdateTimer_.cancel();
 
     // Skip if no controller registered.
     if (controllerList_.empty())
@@ -630,8 +633,13 @@
         return;
     }
 
-    mappingListUpdateTimer_ = getScheduler()->scheduleIn([this] { updateMappingList(false); },
-                                                         MAP_UPDATE_INTERVAL);
+    /*mappingListUpdateTimer_ = getScheduler()->scheduleIn([this] { updateMappingList(false); },
+                                                         MAP_UPDATE_INTERVAL);*/
+    mappingListUpdateTimer_.expires_from_now(MAP_UPDATE_INTERVAL);
+    mappingListUpdateTimer_.async_wait([this](asio::error_code const& ec) {
+        if (ec != asio::error::operation_aborted)
+            updateMappingList(false);
+    });
 
     // Process pending requests if any.
     processPendingRequests(prefIgd);
diff --git a/src/upnp/upnp_control.cpp b/src/upnp/upnp_control.cpp
index 30de6da..bba37d3 100644
--- a/src/upnp/upnp_control.cpp
+++ b/src/upnp/upnp_control.cpp
@@ -26,17 +26,10 @@
 namespace jami {
 namespace upnp {
 
-Controller::Controller()
+Controller::Controller(const std::shared_ptr<UPnPContext>& ctx)
+ : upnpContext_(ctx)
 {
-    try {
-        upnpContext_ = UPnPContext::getUPnPContext();
-    } catch (std::runtime_error& e) {
-        // JAMI_ERR("UPnP context error: %s", e.what());
-    }
-
-    assert(upnpContext_);
     upnpContext_->registerController(this);
-
     // JAMI_DBG("Controller@%p: Created UPnP Controller session", this);
 }