From dbca33cc9903a49e7530f46681788cb972708520 Mon Sep 17 00:00:00 2001
From: Braydon Fuller <courier@braydon.com>
Date: Thu, 3 Oct 2024 16:54:07 -0700
Subject: [PATCH 1/6] Add timeout config for router.

---
 src/apps/mesh/cmd_router.cpp | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/src/apps/mesh/cmd_router.cpp b/src/apps/mesh/cmd_router.cpp
index 2c0cd8d..2a48f9d 100644
--- a/src/apps/mesh/cmd_router.cpp
+++ b/src/apps/mesh/cmd_router.cpp
@@ -218,7 +218,7 @@ struct Router {
     };
 
     std::string routerConfigFile;
-    uint64_t connectionTimeoutUs = 5'000'000;
+    uint64_t connectionTimeoutUs = 20'000'000;
 
     WriterPipeline writer;
     Decompressor decomp;
@@ -293,6 +293,19 @@ struct Router {
     void reconcileConfig() {
         LI << "Loading router config file: " << routerConfigFile;
 
+	try {
+            auto routerConfig = loadRawTaoConfig(routerConfigFile);
+
+	    if (routerConfig.find("timeout")) {
+	        connectionTimeoutUs = stoi(routerConfig.at("timeout").get_string()) * 1'000'000;
+	        LI << "Using configured timeout (seconds): " << (connectionTimeoutUs / 1'000'000);
+	    } else {
+	        LI << "Using default timeout (seconds): " << connectionTimeoutUs / 1'000'000;
+	    }
+	} catch (std::exception &e) {
+            LE << "Failed to parse router timeout in config: " << e.what();
+	}
+
         try {
             auto routerConfig = loadRawTaoConfig(routerConfigFile);
 

From 4b16dc1aa7461274865aa017404efa85693ff6d1 Mon Sep 17 00:00:00 2001
From: Doug Hoyte <doug@hcsw.org>
Date: Fri, 18 Oct 2024 16:35:43 -0400
Subject: [PATCH 2/6] some minor tweaks to the connection timeout, docs

---
 docs/router.md               |  2 ++
 src/apps/mesh/cmd_router.cpp | 28 ++++++++++++++--------------
 2 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/docs/router.md b/docs/router.md
index b3a55a4..2bfe113 100644
--- a/docs/router.md
+++ b/docs/router.md
@@ -18,6 +18,8 @@ The config file must have a section `streams`. Within that, you may have as many
 
 ### Example
 
+    connectionTimeout = 20
+
     streams {
         ## Stream down events from our friend relays
 
diff --git a/src/apps/mesh/cmd_router.cpp b/src/apps/mesh/cmd_router.cpp
index 2a48f9d..5d8c46f 100644
--- a/src/apps/mesh/cmd_router.cpp
+++ b/src/apps/mesh/cmd_router.cpp
@@ -218,7 +218,8 @@ struct Router {
     };
 
     std::string routerConfigFile;
-    uint64_t connectionTimeoutUs = 20'000'000;
+    const uint64_t defaultConnectionTimeoutUs = 20'000'000;
+    uint64_t connectionTimeoutUs = 0;
 
     WriterPipeline writer;
     Decompressor decomp;
@@ -293,19 +294,6 @@ struct Router {
     void reconcileConfig() {
         LI << "Loading router config file: " << routerConfigFile;
 
-	try {
-            auto routerConfig = loadRawTaoConfig(routerConfigFile);
-
-	    if (routerConfig.find("timeout")) {
-	        connectionTimeoutUs = stoi(routerConfig.at("timeout").get_string()) * 1'000'000;
-	        LI << "Using configured timeout (seconds): " << (connectionTimeoutUs / 1'000'000);
-	    } else {
-	        LI << "Using default timeout (seconds): " << connectionTimeoutUs / 1'000'000;
-	    }
-	} catch (std::exception &e) {
-            LE << "Failed to parse router timeout in config: " << e.what();
-	}
-
         try {
             auto routerConfig = loadRawTaoConfig(routerConfigFile);
 
@@ -326,6 +314,18 @@ struct Router {
                 for (const auto &[groupName, spec] : routerConfig.at("streams").get_object()) unneededGroups.erase(groupName);
                 for (const auto &groupName : unneededGroups) streamGroups.erase(groupName);
             }
+
+            // connectionTimeout
+
+            uint64_t newTimeoutUs = defaultConnectionTimeoutUs;
+            if (routerConfig.get_object().contains("connectionTimeout")) {
+                newTimeoutUs = routerConfig.at("connectionTimeout").get_unsigned() * 1'000'000;
+            }
+
+            if (connectionTimeoutUs != newTimeoutUs) {
+                connectionTimeoutUs = newTimeoutUs;
+                LI << "Using connection timeout: " << (connectionTimeoutUs / 1'000'000) << " seconds";
+            }
         } catch (std::exception &e) {
             LE << "Failed to parse router config: " << e.what();
             if (!firstConfigLoadSuccess) ::exit(1);

From bfb9fd14f43eda3ba30a48ceb3af5537110e7435 Mon Sep 17 00:00:00 2001
From: Doug Hoyte <doug@hcsw.org>
Date: Fri, 18 Oct 2024 16:36:03 -0400
Subject: [PATCH 3/6] changelog entries

---
 CHANGES | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/CHANGES b/CHANGES
index feb9717..17b379c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+  * New config param: relay.info.nips which allows you to override the NIPs
+    that are claimed to be supported (requested by ismyhc)
+  * New connectionTimeout parameter in router config (thanks Braydon Fuller!)
+
 1.0.1
   * Prevent exporting a v2 DB using --fried. The packed representation will be
     corrupted. Instead, you should downgrade to 0.9.7 to do the export, or do

From 29d7afe6c3eaebb3b212810630243d012415a926 Mon Sep 17 00:00:00 2001
From: Doug Hoyte <doug@hcsw.org>
Date: Fri, 18 Oct 2024 18:04:21 -0400
Subject: [PATCH 4/6] =?UTF-8?q?hack=20to=20workaround=20uWebsockets=20issu?=
 =?UTF-8?q?e=20preventing=20parsing=20of=20some=20IPv6=20addresses=20(repo?=
 =?UTF-8?q?rted=20by=20Petr=20Krac=C3=ADk)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 CHANGES                           | 2 ++
 src/apps/relay/RelayWebsocket.cpp | 5 +++++
 2 files changed, 7 insertions(+)

diff --git a/CHANGES b/CHANGES
index 17b379c..0ded833 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,8 @@
   * New config param: relay.info.nips which allows you to override the NIPs
     that are claimed to be supported (requested by ismyhc)
   * New connectionTimeout parameter in router config (thanks Braydon Fuller!)
+  * Bugfix: IPv4-mapped IPv6 addresses in X-Real-IP headers were not parsed
+    correctly (reported by Petr KracĂ­k)
 
 1.0.1
   * Prevent exporting a v2 DB using --fried. The packed representation will be
diff --git a/src/apps/relay/RelayWebsocket.cpp b/src/apps/relay/RelayWebsocket.cpp
index 6ba1503..b87de56 100644
--- a/src/apps/relay/RelayWebsocket.cpp
+++ b/src/apps/relay/RelayWebsocket.cpp
@@ -197,6 +197,11 @@ void RelayServer::runWebsocket(ThreadPool<MsgWebsocket>::Thread &thr) {
 
         if (cfg().relay__realIpHeader.size()) {
             auto header = req.getHeader(cfg().relay__realIpHeader.c_str()).toString(); // not string_view: parseIP needs trailing 0 byte
+
+            // HACK: uWebSockets strips leading : characters, which interferes with IPv6 parsing.
+            // This fixes it for the common ::1 and ::ffff:1.2.3.4 cases. FIXME: fix the underlying library.
+            if (header == "1" || header.starts_with("ffff:")) header = std::string("::") + header;
+
             c->ipAddr = parseIP(header);
             if (c->ipAddr.size() == 0) LW << "Couldn't parse IP from header " << cfg().relay__realIpHeader << ": " << header;
         }

From 421463cf4d5e7bc6661adce445c5794b8e73856b Mon Sep 17 00:00:00 2001
From: Doug Hoyte <doug@hcsw.org>
Date: Fri, 18 Oct 2024 18:12:09 -0400
Subject: [PATCH 5/6] show that relay.info.nips must be a string

---
 src/apps/relay/golpe.yaml | 2 +-
 strfry.conf               | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/apps/relay/golpe.yaml b/src/apps/relay/golpe.yaml
index 11b4d5c..e8cbded 100644
--- a/src/apps/relay/golpe.yaml
+++ b/src/apps/relay/golpe.yaml
@@ -31,7 +31,7 @@ config:
     desc: "NIP-11: URL pointing to an image to be used as an icon for the relay"
     default: ""
   - name: relay__info__nips
-    desc: "List of supported lists as JSON array, or empty string to use default. Example: [1,2]"
+    desc: "List of supported lists as JSON array, or empty string to use default. Example: \"[1,2]\""
     default: ""
 
   - name: relay__maxWebsocketPayloadSize
diff --git a/strfry.conf b/strfry.conf
index d05ee77..14d6cb6 100644
--- a/strfry.conf
+++ b/strfry.conf
@@ -68,7 +68,7 @@ relay {
         # NIP-11: URL pointing to an image to be used as an icon for the relay
         icon = ""
 
-        # List of supported lists as JSON array, or empty string to use default. Example: [1,2]
+        # List of supported lists as JSON array, or empty string to use default. Example: "[1,2]"
         nips = ""
     }
 

From 8aa79e41a19b308aae84cb3c9c43fad7d81557a6 Mon Sep 17 00:00:00 2001
From: Doug Hoyte <doug@hcsw.org>
Date: Fri, 18 Oct 2024 18:13:43 -0400
Subject: [PATCH 6/6] release 1.0.2

---
 CHANGES | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGES b/CHANGES
index 0ded833..48c002f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,4 @@
+1.0.2
   * New config param: relay.info.nips which allows you to override the NIPs
     that are claimed to be supported (requested by ismyhc)
   * New connectionTimeout parameter in router config (thanks Braydon Fuller!)