diff --git a/desktop/app/src/init.tsx b/desktop/app/src/init.tsx index 77a2124ee..fcc51d684 100644 --- a/desktop/app/src/init.tsx +++ b/desktop/app/src/init.tsx @@ -47,7 +47,6 @@ import path from 'path'; import fs from 'fs-extra'; import os from 'os'; import {ElectronIpcClientRenderer} from './electronIpc'; -import {checkSocketInUse, makeSocketPath} from 'flipper-server-core'; import {KeytarModule} from 'flipper-server-core/src/utils/keytar'; import {initCompanionEnv} from 'flipper-server-companion'; import ReconnectingWebSocket from 'reconnecting-websocket'; @@ -118,8 +117,6 @@ async function getFlipperServer( const serverUsageEnabled = gatekeepers['flipper_desktop_use_server']; const settings = await loadSettings(); - - const socketPath = await makeSocketPath(); const port = 52342; /** * Only attempt to use the auth token if one is available. Otherwise, @@ -134,7 +131,6 @@ async function getFlipperServer( // check first with the actual TCP socket const searchParams = new URLSearchParams(token ? {token} : {}); const TCPconnectionURL = new URL(`ws://localhost:${port}?${searchParams}`); - const UDSconnectionURL = new URL(`ws+unix://${socketPath}`); /** * Attempt to shutdown a running instance of Flipper server. @@ -159,12 +155,7 @@ async function getFlipperServer( */ if (await checkPortInUse(port)) { console.warn(`[flipper-server] TCP port ${port} is already in use.`); - await shutdown(TCPconnectionURL); - } else if (await checkSocketInUse(socketPath)) { - console.warn(`[flipper-server] UDS socket is already in use.`); - - await shutdown(UDSconnectionURL); } const [homePath, tempPath, desktopPath] = await Promise.all([ @@ -223,9 +214,7 @@ async function getFlipperServer( await server.connect(); await readyForIncomingConnections(server, companionEnv); - return getExternalServer( - os.platform() === 'win32' ? TCPconnectionURL : UDSconnectionURL, - ); + return getExternalServer(TCPconnectionURL); } return getEmbeddedServer(); } diff --git a/desktop/flipper-server-core/package.json b/desktop/flipper-server-core/package.json index a37668370..e9a468e8e 100644 --- a/desktop/flipper-server-core/package.json +++ b/desktop/flipper-server-core/package.json @@ -25,7 +25,6 @@ "flipper-server-companion": "0.0.0", "form-data": "^4.0.0", "fs-extra": "^11.1.0", - "http-proxy": "^1.18.1", "invariant": "^2.2.4", "js-base64": "^3.7.5", "jsonwebtoken": "^9.0.0", @@ -52,7 +51,6 @@ "devDependencies": { "@types/archiver": "^5.3.1", "@types/express": "^4.17.13", - "@types/http-proxy": "^1.17.8", "@types/invariant": "^2.2.35", "@types/jsonwebtoken": "^9.0.1", "@types/memorystream": "^0.3.0", diff --git a/desktop/flipper-server-core/src/server/startServer.tsx b/desktop/flipper-server-core/src/server/startServer.tsx index a9b8a0796..00db40d1e 100644 --- a/desktop/flipper-server-core/src/server/startServer.tsx +++ b/desktop/flipper-server-core/src/server/startServer.tsx @@ -7,18 +7,13 @@ * @format */ -import os from 'os'; - import express, {Express} from 'express'; -import http, {ServerResponse} from 'http'; +import http from 'http'; import path from 'path'; import fs from 'fs-extra'; import {ServerOptions, VerifyClientCallbackSync, WebSocketServer} from 'ws'; import {WEBSOCKET_MAX_MESSAGE_SIZE} from '../app-connectivity/ServerWebSocket'; import {parse} from 'url'; -import {makeSocketPath, checkSocketInUse} from './utilities'; - -import proxy from 'http-proxy'; import exitHook from 'exit-hook'; import {attachSocketServer} from './attachSocketServer'; import {FlipperServerImpl} from '../FlipperServerImpl'; @@ -124,102 +119,23 @@ async function startHTTPServer(config: Config): Promise<{ app.use(express.static(config.staticPath)); - return startProxyServer(config, app); -} - -/** - * Creates and starts the HTTP and proxy servers. - * @param config Server configuration. - * @param app Express app. - * @returns Returns both the app and server configured and - * listening. - */ -async function startProxyServer( - config: Config, - app: Express, -): Promise<{ - app: Express; - server: http.Server; - socket: WebSocketServer; - readyForIncomingConnections: ReadyForConnections; -}> { const server = http.createServer(app); - const socket = addWebsocket(server, config); - - // For now, we only support domain socket access on POSIX-like systems. - // On Windows, a proxy is not created and the server starts - // listening at the specified port. - if (os.platform() === 'win32') { - return new Promise((resolve) => { - console.log(`Starting server on http://localhost:${config.port}`); - const readyForIncomingConnections = ( - serverImpl: FlipperServerImpl, - companionEnv: FlipperServerCompanionEnv, - ): Promise => { - attachSocketServer(socket, serverImpl, companionEnv); - return new Promise((resolve) => { - server.listen(config.port, undefined, () => resolve()); - }); - }; - resolve({app, server, socket, readyForIncomingConnections}); - }); - } - - const socketPath = await makeSocketPath(); - if (await checkSocketInUse(socketPath)) { - console.warn( - `Cannot start flipper-server because socket ${socketPath} is in use.`, - ); - tracker.track('server-socket-already-in-use', {}); - } else { - console.info(`Cleaning up stale socket ${socketPath}`); - await fs.rm(socketPath, {force: true}); - } - - const proxyServer: proxy | undefined = proxy.createProxyServer({ - target: {host: 'localhost', port: 0, socketPath}, - autoRewrite: true, - ws: true, - }); - - console.log('Starting socket server on ', socketPath); - if (proxyServer) { - console.log(`Starting proxy server on http://localhost:${config.port}`); - } + const socket = attachWS(server, config); exitHook(() => { console.log('Shutdown server'); - proxyServer?.close(); server.close(); - - console.log('Cleaning up socket on exit:', socketPath); - // This *must* run synchronously and we're not blocking any UI loop by definition. - // eslint-disable-next-line node/no-sync - fs.rmSync(socketPath, {force: true}); - }); - - proxyServer?.on('error', (err, _req, _res) => { - console.warn('Error in proxy server:', err); - tracker.track('server-proxy-error', {error: err.message}); - - // As it stands, if the proxy fails, which is the one - // listening on the supplied TCP port, then we should exit. - // Otherwise we risk staying in an invalid state, unable - // to recover, and thus preventing us to serve incoming requests. - // Bear in mind that exiting the process will trigger the exit hook - // defined above which will clean and close the sockets. - process.exit(0); }); return new Promise((resolve) => { + console.log(`Starting server on http://localhost:${config.port}`); const readyForIncomingConnections = ( serverImpl: FlipperServerImpl, companionEnv: FlipperServerCompanionEnv, ): Promise => { attachSocketServer(socket, serverImpl, companionEnv); return new Promise((resolve) => { - proxyServer?.listen(config.port); - server.listen(socketPath, undefined, () => { + server.listen(config.port, undefined, () => { tracker.track('server-started', { port: config.port, }); @@ -238,7 +154,7 @@ async function startProxyServer( * incoming connections origin. * @returns Returns the created WS. */ -function addWebsocket(server: http.Server, config: Config) { +function attachWS(server: http.Server, config: Config) { const localhost = 'localhost'; const localhostIPV4 = `localhost:${config.port}`; const localhostIPV6 = `[::1]:${config.port}`; diff --git a/desktop/flipper-server-core/src/server/utilities.tsx b/desktop/flipper-server-core/src/server/utilities.tsx index 3ef9822f3..2ff26024c 100644 --- a/desktop/flipper-server-core/src/server/utilities.tsx +++ b/desktop/flipper-server-core/src/server/utilities.tsx @@ -39,63 +39,3 @@ export async function checkPortInUse(port: number): Promise { .listen(port); }); } - -/** - * Checks if a socket is in used for given path. - * If the path doesn't exist then is not in use. If it does, - * create a socket client and attempt to connect to it. - * If the connection is established, then there's a process - * already listening. Otherwise, it kind of indicates the - * contrary. - * @param path Path used instead of port number. - * @returns True or false dependning on whether the socket is in - * use or not. - */ -export async function checkSocketInUse(path: string): Promise { - if (!(await fs.pathExists(path))) { - return false; - } - return new Promise((resolve, _reject) => { - const client = net - .createConnection(path, () => { - resolve(true); - client.destroy(); - }) - .on('error', (e) => { - if (e.message.includes('ECONNREFUSED')) { - resolve(false); - } else { - console.warn( - `[conn] Socket ${path} is in use, but we don't know why.`, - e, - ); - resolve(false); - } - client.destroy(); - }); - }); -} - -/** - * Creates a socket path. Used to open the socket at location. - * Format: flipper-server-${userInfo}.sock - * @returns The created socket path. - */ -export async function makeSocketPath(): Promise { - const runtimeDir = xdgBasedir.runtime || '/tmp'; - await fs.mkdirp(runtimeDir); - const filename = `flipper-server-${os.userInfo().uid}.sock`; - const path = `${runtimeDir}/${filename}`; - - // Depending on the OS this is between 104 and 108: - // https://unix.stackexchange.com/a/367012/10198 - if (path.length >= 104) { - console.warn( - 'Ignoring XDG_RUNTIME_DIR as it would exceed the total limit for domain socket paths. See man 7 unix.', - ); - // Even with the INT32_MAX userid, we should have plenty of room. - return `/tmp/${filename}`; - } - - return path; -}