gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libeufin] 01/02: Falling back to IPv4, when IPv6 isn't supported.


From: gnunet
Subject: [libeufin] 01/02: Falling back to IPv4, when IPv6 isn't supported.
Date: Wed, 18 Jan 2023 22:46:25 +0100

This is an automated email from the git hooks/post-receive script.

ms pushed a commit to branch master
in repository libeufin.

commit a8413e5315b078a1833beb597de400ad1dbfe2ee
Author: MS <ms@taler.net>
AuthorDate: Wed Jan 18 22:42:57 2023 +0100

    Falling back to IPv4, when IPv6 isn't supported.
---
 nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt  | 11 ++-
 .../tech/libeufin/nexus/server/NexusServer.kt      | 23 ------
 .../src/main/kotlin/tech/libeufin/sandbox/Main.kt  | 51 +++++---------
 util/build.gradle                                  |  2 +
 util/src/main/kotlin/startServer.kt                | 81 ++++++++++++++++++++++
 util/src/test/kotlin/StartServerTest.kt            | 31 +++++++++
 6 files changed, 139 insertions(+), 60 deletions(-)

diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
index df1fe2d8..6795f8e0 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
@@ -24,7 +24,6 @@ import com.github.ajalt.clikt.parameters.arguments.argument
 import org.jetbrains.exposed.sql.transactions.transaction
 import org.slf4j.Logger
 import org.slf4j.LoggerFactory
-import tech.libeufin.nexus.server.serverMain
 import tech.libeufin.util.CryptoUtil.hashpw
 import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
 import com.github.ajalt.clikt.parameters.types.int
@@ -82,7 +81,15 @@ class Serve : CliktCommand("Run nexus HTTP server") {
             )
             exitProcess(0)
         }
-        serverMain(port, localhostOnly, ipv4Only)
+        logger.info("Starting Nexus on port ${this.port}")
+        startServerWithIPv4Fallback(
+            options = StartServerOptions(
+                ipv4OnlyOpt = this.ipv4Only,
+                localhostOnlyOpt = this.localhostOnly,
+                portOpt = this.port
+            ),
+            app = nexusApp
+        )
     }
 }
 
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt
index 1d00fb92..b8c33065 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt
@@ -1048,26 +1048,3 @@ val nexusApp: Application.() -> Unit = {
         }
     }
 }
-fun serverMain(port: Int, localhostOnly: Boolean, ipv4Only: Boolean) {
-    val server = embeddedServer(
-        Netty,
-        environment = applicationEngineEnvironment {
-            connector {
-                this.port = port
-                this.host = if (localhostOnly) "127.0.0.1" else "0.0.0.0"
-            }
-            if (!ipv4Only) connector {
-                this.port = port
-                this.host = if (localhostOnly) "[::1]" else "[::]"
-            }
-            module(nexusApp)
-        }
-    )
-    logger.info("LibEuFin Nexus running on port $port")
-    try {
-        server.start(wait = true)
-    } catch (e: BindException) {
-        logger.error(e.message)
-        exitProcess(1)
-    }
-}
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
index 48f22ca9..3bfce37a 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
@@ -60,7 +60,6 @@ import org.w3c.dom.Document
 import startServer
 import tech.libeufin.util.*
 import java.math.BigDecimal
-import java.net.BindException
 import java.net.URL
 import java.security.interfaces.RSAPublicKey
 import javax.xml.bind.JAXBContext
@@ -355,8 +354,11 @@ class Serve : CliktCommand("Run sandbox HTTP server") {
         WITH_AUTH = auth
         setLogLevel(logLevel)
         if (WITH_AUTH && adminPassword == null) {
-            System.err.println("Error: auth is enabled, but env 
LIBEUFIN_SANDBOX_ADMIN_PASSWORD is not."
-            + " (Option --no-auth exists for tests)")
+            System.err.println(
+                "Error: auth is enabled, but env " +
+                        "LIBEUFIN_SANDBOX_ADMIN_PASSWORD is not."
+                        + " (Option --no-auth exists for tests)"
+            )
             exitProcess(1)
         }
         execThrowableOrTerminate { 
dbCreateTables(getDbConnFromEnv(SANDBOX_DB_ENV_VAR_NAME)) }
@@ -376,7 +378,16 @@ class Serve : CliktCommand("Run sandbox HTTP server") {
         }
         SMS_TAN_CMD = smsTan
         EMAIL_TAN_CMD = emailTan
-        serverMain(port, localhostOnly, ipv4Only)
+
+        logger.info("Starting Sandbox on port ${this.port}")
+        startServerWithIPv4Fallback(
+            options = StartServerOptions(
+                ipv4OnlyOpt = this.ipv4Only,
+                localhostOnlyOpt = this.localhostOnly,
+                portOpt = this.port
+            ),
+            app = sandboxApp
+        )
     }
 }
 
@@ -1606,34 +1617,4 @@ val sandboxApp: Application.() -> Unit = {
             }
         }
     }
-}
-
-fun serverMain(port: Int, localhostOnly: Boolean, ipv4Only: Boolean) {
-    val server = embeddedServer(
-        Netty,
-        environment = applicationEngineEnvironment{
-            connector {
-                this.port = port
-                this.host = if (localhostOnly) "127.0.0.1" else "0.0.0.0"
-            }
-            if (!ipv4Only) connector {
-                this.port = port
-                this.host = if (localhostOnly) "[::1]" else "[::]"
-            }
-            // parentCoroutineContext = Dispatchers.Main
-            module(sandboxApp)
-        },
-        configure = {
-            connectionGroupSize = 1
-            workerGroupSize = 1
-            callGroupSize = 1
-        }
-    )
-    logger.info("LibEuFin Sandbox running on port $port")
-    try {
-        server.start(wait = true)
-    } catch (e: BindException) {
-        logger.error(e.message)
-        exitProcess(1)
-    }
-}
+}
\ No newline at end of file
diff --git a/util/build.gradle b/util/build.gradle
index aa2334fb..d2bb682c 100644
--- a/util/build.gradle
+++ b/util/build.gradle
@@ -56,6 +56,8 @@ dependencies {
     testImplementation group: 'junit', name: 'junit', version: '4.13.2'
     testImplementation 'org.jetbrains.kotlin:kotlin-test-junit:1.5.21'
     testImplementation 'org.jetbrains.kotlin:kotlin-test:1.5.21'
+    testImplementation project(":sandbox")
+    testImplementation project(":nexus")
 
 }
 
diff --git a/util/src/main/kotlin/startServer.kt 
b/util/src/main/kotlin/startServer.kt
new file mode 100644
index 00000000..cabd91a7
--- /dev/null
+++ b/util/src/main/kotlin/startServer.kt
@@ -0,0 +1,81 @@
+package tech.libeufin.util
+
+import io.ktor.server.application.*
+import io.ktor.server.engine.*
+import io.ktor.server.netty.*
+import io.netty.channel.unix.Errors
+import logger
+import java.net.BindException
+import kotlin.system.exitProcess
+
+const val EAFNOSUPPORT = -97 // Netty defines errors negatively.
+class StartServerOptions(
+    var ipv4OnlyOpt: Boolean,
+    val localhostOnlyOpt: Boolean,
+    val portOpt: Int
+)
+
+// Core function starting the server.
+private fun serverMain(options: StartServerOptions, app: Application.() -> 
Unit) {
+    val server = embeddedServer(
+        Netty,
+        environment = applicationEngineEnvironment {
+            connector {
+                this.port = options.portOpt
+                this.host = if (options.localhostOnlyOpt) "127.0.0.1" else 
"0.0.0.0"
+            }
+            if (!options.ipv4OnlyOpt) connector {
+                this.port = options.portOpt
+                this.host = if (options.localhostOnlyOpt) "[::1]" else "[::]"
+            }
+            module(app)
+        },
+        configure = {
+            connectionGroupSize = 1
+            workerGroupSize = 1
+            callGroupSize = 1
+        }
+    )
+    /**
+     * NOTE: excepted server still need the stop(), otherwise
+     * it leaves the port locked and prevents the IPv4 retry.
+     */
+    try {
+        server.start(wait = true)
+    } catch (e: Exception) {
+        server.stop()
+        logger.debug("Rethrowing: ${e.message}")
+        throw e // Rethrowing for retry policies.
+    }
+}
+
+// Wrapper function that retries when IPv6 fails.
+fun startServerWithIPv4Fallback(
+    options: StartServerOptions,
+    app: Application.() -> Unit
+) {
+    var maybeRetry = false
+    try {
+        serverMain(options, app)
+    } catch (e: Exception) {
+        logger.warn(e.message)
+        // Find reasons to retry.
+        if (e is Errors.NativeIoException) {
+            logger.debug("errno: ${e.expectedErr()}")
+            if ((e.expectedErr() == EAFNOSUPPORT) && (!options.ipv4OnlyOpt))
+                maybeRetry = true
+        }
+    }
+    // Fail, if no retry policy applies.  The catch block above logged the 
error.
+    if (!maybeRetry) {
+        exitProcess(1)
+    }
+    logger.info("Retrying to start the server on IPv4")
+    options.ipv4OnlyOpt = true
+    try {
+        serverMain(options, app)
+    } catch (e: Exception) {
+        logger.error(e.message)
+        exitProcess(1)
+    }
+}
\ No newline at end of file
diff --git a/util/src/test/kotlin/StartServerTest.kt 
b/util/src/test/kotlin/StartServerTest.kt
new file mode 100644
index 00000000..dbb56075
--- /dev/null
+++ b/util/src/test/kotlin/StartServerTest.kt
@@ -0,0 +1,31 @@
+import org.junit.Ignore
+import org.junit.Test
+import tech.libeufin.nexus.server.nexusApp
+import tech.libeufin.sandbox.sandboxApp
+import tech.libeufin.util.StartServerOptions
+import tech.libeufin.util.startServerWithIPv4Fallback
+
+class StartServerTest {
+    @Test
+    fun sandboxStart() {
+        startServerWithIPv4Fallback(
+            options = StartServerOptions(
+                ipv4OnlyOpt = false,
+                localhostOnlyOpt = false,
+                portOpt = 5000
+            ),
+            app = sandboxApp
+        )
+    }
+    @Test
+    fun nexusStart() {
+        startServerWithIPv4Fallback(
+            options = StartServerOptions(
+                ipv4OnlyOpt = false,
+                localhostOnlyOpt = true,
+                portOpt = 5000
+            ),
+            app = nexusApp
+        )
+    }
+}
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]