[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.