From bc882e2adf12eef92af449da4f7c0f6e117771e3 Mon Sep 17 00:00:00 2001 From: Yuchen Shi Date: Thu, 5 Nov 2020 08:38:14 -0800 Subject: [PATCH] Work around Java emulators + WSL connectivity issues. (#2780) --- CHANGELOG.md | 1 + src/emulator/controller.ts | 12 +++++++++++- src/emulator/downloadableEmulators.ts | 14 ++++++++++++++ src/utils.ts | 8 ++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e69de29bb2d..0eef5daa6ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -0,0 +1 @@ +- Work around Java emulators + WSL connectivity issues. diff --git a/src/emulator/controller.ts b/src/emulator/controller.ts index c24c55857f5..fd80bbdc867 100644 --- a/src/emulator/controller.ts +++ b/src/emulator/controller.ts @@ -41,10 +41,20 @@ import { FLAG_EXPORT_ON_EXIT_NAME } from "./commandUtils"; import { fileExistsSync } from "../fsutils"; async function getAndCheckAddress(emulator: Emulators, options: any): Promise
{ - const host = Constants.normalizeHost( + let host = Constants.normalizeHost( options.config.get(Constants.getHostKey(emulator), Constants.getDefaultHost(emulator)) ); + if (host === "localhost" && utils.isRunningInWSL()) { + // HACK(https://github.com/firebase/firebase-tools-ui/issues/332): Use IPv4 + // 127.0.0.1 instead of localhost. This, combined with the hack in + // downloadableEmulators.ts, forces the emulator to listen on IPv4 ONLY. + // The CLI (including the hub) will also consistently report 127.0.0.1, + // causing clients to connect via IPv4 only (which mitigates the problem of + // some clients resolving localhost to IPv6 and get connection refused). + host = "127.0.0.1"; + } + const portVal = options.config.get(Constants.getPortKey(emulator), undefined); let port; let findAvailablePort = false; diff --git a/src/emulator/downloadableEmulators.ts b/src/emulator/downloadableEmulators.ts index 27b0afc67f6..ffb0b791ce6 100644 --- a/src/emulator/downloadableEmulators.ts +++ b/src/emulator/downloadableEmulators.ts @@ -168,6 +168,20 @@ function _getCommand( const cmdLineArgs = baseCmd.args.slice(); + if ( + baseCmd.binary === "java" && + utils.isRunningInWSL() && + (!args.host || !args.host.includes(":")) + ) { + // HACK(https://github.com/firebase/firebase-tools-ui/issues/332): Force + // Java to use IPv4 sockets in WSL (unless IPv6 address explicitly used). + // Otherwise, Java will open a tcp6 socket (even if IPv4 address is used), + // which handles both 4/6 on Linux but NOT IPv4 from the host to WSL. + // This is a hack because it breaks all IPv6 connections as a side effect. + // See: https://docs.oracle.com/javase/8/docs/api/java/net/doc-files/net-properties.html + cmdLineArgs.unshift("-Djava.net.preferIPv4Stack=true"); // first argument + } + const logger = EmulatorLogger.forEmulator(emulator); Object.keys(args).forEach((key) => { if (!baseCmd.optionalArgs.includes(key)) { diff --git a/src/utils.ts b/src/utils.ts index b448f32957c..259b460dd8b 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -478,3 +478,11 @@ export function datetimeString(d: Date): string { export function isCloudEnvironment() { return !!process.env.CODESPACES; } + +/** + * Indicates whether or not this process is likely to be running in WSL. + * @return true if we're likely in WSL, false otherwise + */ +export function isRunningInWSL(): boolean { + return !!process.env.WSL_DISTRO_NAME; +}