From 6642a6254257bb2139cf5c8f7e4abfc948a09900 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois-Simon=20Fauteux-Chapleau?=
 <francois-simon.fauteux-chapleau@savoirfairelinux.com>
Date: Wed, 4 Dec 2024 12:23:00 -0500
Subject: [PATCH] upnpctrl: don't open mappings by default

The UPnPContext class currently has hardcoded limits on the number of
mappings that need to be "available" at any given time. This patch adds
the ability to modify these limits and sets them to zero in the upnpctrl
tool. This changes the behavior of the tool in two ways:
1) setting the minimum limit to zero means that no mappings are opened
   when upnpctrl starts;
2) setting the maximum limit to zero means that the "close" command will
   always cause the relevant mapping to be closed immediately instead of
   (potentially) being put back in the list of available mappings.

Change-Id: Idcf4262ce80a8b39f19ce7d3a201b40b3ea56911
---
 include/upnp/upnp_context.h | 15 +++++++++++++--
 tools/upnp/upnpctrl.cpp     |  2 ++
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/include/upnp/upnp_context.h b/include/upnp/upnp_context.h
index 46254dc..57f6d82 100644
--- a/include/upnp/upnp_context.h
+++ b/include/upnp/upnp_context.h
@@ -138,6 +138,17 @@ public:
     // then the state of all pending mappings is set to FAILED.
     void setIgdDiscoveryTimeout(std::chrono::milliseconds timeout);
 
+    // Set limits on the number of "available" mappings that the UPnPContext
+    // can keep at any given time. An available mapping is one that has been
+    // opened, but isn't being used by any Controller. The context will attempt
+    // to close or open mappings as needed to keep the number of available
+    // mappings between `minCount` and `maxCount`.
+    void setAvailableMappingsLimits(PortType type, unsigned minCount, unsigned maxCount) {
+        unsigned index = (type == PortType::TCP) ? 0 : 1;
+        maxAvailableMappings_[index] = maxCount;
+        minAvailableMappings_[index] = (minCount <= maxCount) ? minCount : 0;
+    }
+
 private:
     // Initialization
     void init();
@@ -286,8 +297,8 @@ private:
 
     // Minimum and maximum limits on the number of available
     // mappings to keep in the list at any given time
-    static constexpr unsigned minAvailableMappings_[2] {4, 8};
-    static constexpr unsigned maxAvailableMappings_[2] {8, 12};
+    unsigned minAvailableMappings_[2] {4, 8};
+    unsigned maxAvailableMappings_[2] {8, 12};
     unsigned getMinAvailableMappings(PortType type) {
         unsigned index = (type == PortType::TCP) ? 0 : 1;
         return minAvailableMappings_[index];
diff --git a/tools/upnp/upnpctrl.cpp b/tools/upnp/upnpctrl.cpp
index 7c4febf..ba13de5 100644
--- a/tools/upnp/upnpctrl.cpp
+++ b/tools/upnp/upnpctrl.cpp
@@ -62,6 +62,8 @@ main(int argc, char** argv)
     auto ioContext  = std::make_shared<asio::io_context>();
     std::shared_ptr<dht::log::Logger> logger = dht::log::getStdLogger();
     auto upnpContext = std::make_shared<dhtnet::upnp::UPnPContext>(ioContext, logger);
+    upnpContext->setAvailableMappingsLimits(dhtnet::upnp::PortType::TCP, 0, 0);
+    upnpContext->setAvailableMappingsLimits(dhtnet::upnp::PortType::UDP, 0, 0);
 
     auto ioContextRunner = std::make_shared<std::thread>([context = ioContext]() {
         try {
-- 
GitLab