IJPL-171206 WslProxy: Require application address instead of port to avoid IPv4/IPv6 confusion

(cherry picked from commit 0090e4166b7d69fcb3b02d4bdac378afa3a1929b)

IJ-CR-150935

GitOrigin-RevId: d029181951626dafe9ead9456a8e452d8d9f0410
This commit is contained in:
Vladimir Lagunov
2024-12-04 18:53:44 +01:00
committed by intellij-monorepo-bot
parent 1b51229ac7
commit fd8609fc38
2 changed files with 19 additions and 12 deletions

View File

@@ -122,8 +122,7 @@ import org.jetbrains.jps.model.java.compiler.JavaCompilers;
import org.jvnet.winp.Priority; import org.jvnet.winp.Priority;
import org.jvnet.winp.WinProcess; import org.jvnet.winp.WinProcess;
import javax.tools.JavaCompiler; import javax.tools.*;
import javax.tools.ToolProvider;
import java.awt.*; import java.awt.*;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -137,8 +136,8 @@ import java.nio.file.Paths;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.List;
import java.util.*; import java.util.*;
import java.util.List;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@@ -1137,8 +1136,10 @@ public final class BuildManager implements Disposable {
return startListening(inetAddress); return startListening(inetAddress);
} }
private synchronized int getWslPort(WSLDistribution dist, int localPort) { private synchronized int getWslPort(WSLDistribution dist, InetSocketAddress localAddress) {
return myWslProxyCache.computeIfAbsent(dist.getId() + ":" + localPort, key -> new WslProxy(dist, localPort)).getWslIngressPort(); return myWslProxyCache
.computeIfAbsent(dist.getId() + ":" + localAddress, key -> new WslProxy(dist, localAddress))
.getWslIngressPort();
} }
private synchronized void cleanWslProxies(WSLDistribution dist) { private synchronized void cleanWslProxies(WSLDistribution dist) {
@@ -1354,9 +1355,9 @@ public final class BuildManager implements Disposable {
final CompilerWorkspaceConfiguration config = CompilerWorkspaceConfiguration.getInstance(project); final CompilerWorkspaceConfiguration config = CompilerWorkspaceConfiguration.getInstance(project);
InetAddress listenAddress = InetAddress.getLoopbackAddress(); InetAddress listenAddress = InetAddress.getLoopbackAddress();
int listenPort = ensureListening(listenAddress); InetSocketAddress listenSocketAddress = new InetSocketAddress(listenAddress, ensureListening(listenAddress));
String buildProcessConnectHost = listenAddress.getHostAddress(); String buildProcessConnectHost = listenAddress.getHostAddress();
int buildProcessConnectPort = listenPort; int buildProcessConnectPort = listenSocketAddress.getPort();
BuildCommandLineBuilder cmdLine; BuildCommandLineBuilder cmdLine;
WslPath wslPath = WslPath.parseWindowsUncPath(vmExecutablePath); WslPath wslPath = WslPath.parseWindowsUncPath(vmExecutablePath);
@@ -1367,7 +1368,7 @@ public final class BuildManager implements Disposable {
} }
cmdLine = new WslBuildCommandLineBuilder(project, sdkDistribution, wslPath.getLinuxPath(), progressIndicator); cmdLine = new WslBuildCommandLineBuilder(project, sdkDistribution, wslPath.getLinuxPath(), progressIndicator);
buildProcessConnectHost = "127.0.0.1"; // WslProxy listen address on linux side buildProcessConnectHost = "127.0.0.1"; // WslProxy listen address on linux side
buildProcessConnectPort = getWslPort(sdkDistribution, listenPort); buildProcessConnectPort = getWslPort(sdkDistribution, listenSocketAddress);
} }
else { else {
if (projectWslDistribution != null) { if (projectWslDistribution != null) {

View File

@@ -14,6 +14,7 @@ import kotlinx.coroutines.channels.ClosedReceiveChannelException
import org.jetbrains.annotations.ApiStatus import org.jetbrains.annotations.ApiStatus
import java.io.IOException import java.io.IOException
import java.net.InetAddress import java.net.InetAddress
import java.net.InetSocketAddress
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.nio.ByteOrder import java.nio.ByteOrder
import kotlin.coroutines.coroutineContext import kotlin.coroutines.coroutineContext
@@ -33,7 +34,11 @@ import kotlin.coroutines.coroutineContext
* *
*/ */
@ApiStatus.Internal @ApiStatus.Internal
class WslProxy(distro: AbstractWslDistribution, private val applicationPort: Int) : Disposable { class WslProxy(distro: AbstractWslDistribution, private val applicationAddress: InetSocketAddress) : Disposable {
@Deprecated("Use the construction with the application address." +
" This constructor can lead to sporadic 'connection refused' errors in case of IPv4/IPv6 confusion.")
constructor(distro: AbstractWslDistribution, applicationPort: Int) : this(distro, InetSocketAddress("127.0.0.1", applicationPort))
private companion object { private companion object {
private val LOG = logger<WslProxy>() private val LOG = logger<WslProxy>()
@@ -163,8 +168,9 @@ class WslProxy(distro: AbstractWslDistribution, private val applicationPort: Int
socket socket
} }
val winToWin = scope.async { val winToWin = scope.async {
LOG.info("Connecting to app: $127.0.0.1:$applicationPort") LOG.info("Connecting to app: $applicationAddress")
val socket = aSocket(ActorSelectorManager(scope.coroutineContext)).tcp().tryConnect("127.0.0.1", applicationPort) val socket = aSocket(ActorSelectorManager(scope.coroutineContext)).tcp()
.tryConnect(applicationAddress.hostString, applicationAddress.port)
LOG.info("Connected to app") LOG.info("Connected to app")
socket socket
} }
@@ -178,7 +184,7 @@ class WslProxy(distro: AbstractWslDistribution, private val applicationPort: Int
launch(CoroutineName("WinWin->WinLin $linuxEgressPort")) { launch(CoroutineName("WinWin->WinLin $linuxEgressPort")) {
connectChannels(winToWinSocket.openReadChannel(), winToLinSocket.openWriteChannel(true)) connectChannels(winToWinSocket.openReadChannel(), winToLinSocket.openWriteChannel(true))
}.invokeOnCompletion { closeSockets() } }.invokeOnCompletion { closeSockets() }
launch(CoroutineName("WinLin->WinWin $applicationPort")) { launch(CoroutineName("WinLin->WinWin $applicationAddress")) {
connectChannels(winToLinSocket.openReadChannel(), winToWinSocket.openWriteChannel(true)) connectChannels(winToLinSocket.openReadChannel(), winToWinSocket.openWriteChannel(true))
}.invokeOnCompletion { closeSockets() } }.invokeOnCompletion { closeSockets() }
} }