From 11661cb7d9fc9e2884131852b3a1800f623b81c3 Mon Sep 17 00:00:00 2001 From: anonvector <258689915+anonvector@users.noreply.github.com> Date: Tue, 10 Mar 2026 08:55:57 +0100 Subject: [PATCH] v2.3.1: Fix HTTP proxy reliability issues - Fix copyStream flush strategy: flush after every write instead of relying on unreliable InputStream.available() which caused data to stay buffered indefinitely, increasing latency and causing stalls - Fix CONNECT half-close: use shutdownOutput() instead of close() to avoid killing the socket while server is still sending response data - Fix idle timeout: use 5-minute relay timeout instead of infinite (0), preventing hung threads on stalled connections - Bump versionCode to 40 Co-Authored-By: Claude Opus 4.6 (1M context) --- app/build.gradle.kts | 4 ++-- .../java/app/slipnet/tunnel/HttpProxyServer.kt | 15 ++++++--------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 612ed26..837f6e9 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -14,8 +14,8 @@ plugins { } val minSdkVersion = 24 -val appVersionName = "2.3" -val appVersionCode = 39 +val appVersionName = "2.3.1" +val appVersionCode = 40 val cargoProfile = (findProperty("CARGO_PROFILE") as String?) ?: run { val isRelease = gradle.startParameter.taskNames.any { it.contains("Release", ignoreCase = true) } if (isRelease) "release" else "debug" diff --git a/app/src/main/java/app/slipnet/tunnel/HttpProxyServer.kt b/app/src/main/java/app/slipnet/tunnel/HttpProxyServer.kt index 5ef507e..74c05f3 100644 --- a/app/src/main/java/app/slipnet/tunnel/HttpProxyServer.kt +++ b/app/src/main/java/app/slipnet/tunnel/HttpProxyServer.kt @@ -29,6 +29,7 @@ object HttpProxyServer { private const val BIND_RETRY_DELAY_MS = 200L private const val BUFFER_SIZE = 32768 private const val TCP_CONNECT_TIMEOUT_MS = 30000 + private const val RELAY_IDLE_TIMEOUT_MS = 300000 private var socksHost: String = "127.0.0.1" private var socksPort: Int = 1080 @@ -210,7 +211,7 @@ object HttpProxyServer { clientOutput.write("HTTP/1.1 200 Connection Established\r\n\r\n".toByteArray()) clientOutput.flush() - clientSocket.soTimeout = 0 + clientSocket.soTimeout = RELAY_IDLE_TIMEOUT_MS // Bridge bidirectionally remoteSocket.use { remote -> @@ -222,7 +223,7 @@ object HttpProxyServer { copyStream(clientInput, remoteOutput) } catch (_: Exception) { } finally { - try { remoteOutput.close() } catch (_: Exception) {} + try { remote.shutdownOutput() } catch (_: Exception) {} } }, "http-proxy-c2s") t1.isDaemon = true @@ -331,7 +332,7 @@ object HttpProxyServer { remoteOutput.write("\r\n".toByteArray()) remoteOutput.flush() - clientSocket.soTimeout = 0 + clientSocket.soTimeout = RELAY_IDLE_TIMEOUT_MS // Bidirectional bridge: forwards request body (if any) and response. // Server will close after response due to Connection: close. @@ -420,17 +421,13 @@ object HttpProxyServer { } private fun copyStream(input: InputStream, output: OutputStream) { - val buffered = BufferedOutputStream(output, BUFFER_SIZE) val buffer = ByteArray(BUFFER_SIZE) while (!Thread.currentThread().isInterrupted) { val bytesRead = input.read(buffer) if (bytesRead == -1) break - buffered.write(buffer, 0, bytesRead) - if (bytesRead < BUFFER_SIZE || input.available() == 0) { - buffered.flush() - } + output.write(buffer, 0, bytesRead) + output.flush() } - buffered.flush() } }