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

View File

@@ -14,6 +14,7 @@ import kotlinx.coroutines.channels.ClosedReceiveChannelException
import org.jetbrains.annotations.ApiStatus
import java.io.IOException
import java.net.InetAddress
import java.net.InetSocketAddress
import java.nio.ByteBuffer
import java.nio.ByteOrder
import kotlin.coroutines.coroutineContext
@@ -33,7 +34,11 @@ import kotlin.coroutines.coroutineContext
*
*/
@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 val LOG = logger<WslProxy>()
@@ -163,8 +168,9 @@ class WslProxy(distro: AbstractWslDistribution, private val applicationPort: Int
socket
}
val winToWin = scope.async {
LOG.info("Connecting to app: $127.0.0.1:$applicationPort")
val socket = aSocket(ActorSelectorManager(scope.coroutineContext)).tcp().tryConnect("127.0.0.1", applicationPort)
LOG.info("Connecting to app: $applicationAddress")
val socket = aSocket(ActorSelectorManager(scope.coroutineContext)).tcp()
.tryConnect(applicationAddress.hostString, applicationAddress.port)
LOG.info("Connected to app")
socket
}
@@ -178,7 +184,7 @@ class WslProxy(distro: AbstractWslDistribution, private val applicationPort: Int
launch(CoroutineName("WinWin->WinLin $linuxEgressPort")) {
connectChannels(winToWinSocket.openReadChannel(), winToLinSocket.openWriteChannel(true))
}.invokeOnCompletion { closeSockets() }
launch(CoroutineName("WinLin->WinWin $applicationPort")) {
launch(CoroutineName("WinLin->WinWin $applicationAddress")) {
connectChannels(winToLinSocket.openReadChannel(), winToWinSocket.openWriteChannel(true))
}.invokeOnCompletion { closeSockets() }
}