Summary: Right now, this simply avoids trying to create a server instance if one appears to be already running. In a future change, we may decide to kill the existing instance and replace it with a new one. But, in this case, running this as is will be useful as it will provide the connection URL with the auth token. Also remove flipper server dependency from finding installation. In this case, we don't need it and can use `os.getPlatform()` instead. Reviewed By: antonk52 Differential Revision: D46144843 fbshipit-source-id: 2922843b916d37e0126e43ae65a622f87a6920ec
102 lines
2.8 KiB
TypeScript
102 lines
2.8 KiB
TypeScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @format
|
|
*/
|
|
|
|
import os from 'os';
|
|
import xdgBasedir from 'xdg-basedir';
|
|
import net from 'net';
|
|
import fs from 'fs-extra';
|
|
|
|
/**
|
|
* Checks if a port is in use.
|
|
* @param port The port to check.
|
|
* @returns True if the port is in use. Otherwise, false.
|
|
*/
|
|
export async function checkPortInUse(port: number): Promise<boolean> {
|
|
interface HttpError extends Error {
|
|
code?: string;
|
|
}
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const tester = net
|
|
.createServer()
|
|
.once('error', function (err: HttpError) {
|
|
if (err.code != 'EADDRINUSE') return reject(err);
|
|
resolve(true);
|
|
})
|
|
.once('listening', function () {
|
|
tester
|
|
.once('close', function () {
|
|
resolve(false);
|
|
})
|
|
.close();
|
|
})
|
|
.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<boolean> {
|
|
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<string> {
|
|
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;
|
|
}
|