Integrate the Android client with native desktop pairing, remote terminal and SSH/SFTP sessions, keyboard controls, file reading and Agent conversations. Preserve authenticated connection ownership and per-device input permissions. Validation: all ten required GitHub checks passed, including five native test platforms and both macOS release workspace checks.
54 lines
2.0 KiB
JavaScript
54 lines
2.0 KiB
JavaScript
import net from 'node:net';
|
|
|
|
const MAX_PROXY_CONNECTIONS = 2;
|
|
const MAX_PROXY_CHUNK = 2 * 1024 * 1024 + 1024;
|
|
|
|
/**
|
|
* Forward encrypted bytes from a loopback-only socket to the LAN relay. The
|
|
* desktop connector therefore has a private wss://127.0.0.1 entry while the
|
|
* phone uses the separately bound HTTPS/WSS listener.
|
|
*/
|
|
export async function startLoopbackProxy(targetHost, targetPort) {
|
|
const sockets = new Set();
|
|
const connections = new Set();
|
|
const server = net.createServer(socket => {
|
|
if (connections.size >= MAX_PROXY_CONNECTIONS) { socket.destroy(); return; }
|
|
connections.add(socket);
|
|
sockets.add(socket);
|
|
socket.setNoDelay(true);
|
|
const upstream = net.createConnection({ host: targetHost, port: targetPort });
|
|
sockets.add(upstream);
|
|
upstream.setNoDelay(true);
|
|
const close = () => {
|
|
socket.destroy(); upstream.destroy(); connections.delete(socket);
|
|
sockets.delete(socket); sockets.delete(upstream);
|
|
};
|
|
socket.on('data', bytes => {
|
|
if (bytes.length > MAX_PROXY_CHUNK) { close(); return; }
|
|
if (!upstream.write(bytes)) socket.pause();
|
|
});
|
|
upstream.on('drain', () => socket.resume());
|
|
upstream.on('data', bytes => {
|
|
if (bytes.length > MAX_PROXY_CHUNK) { close(); return; }
|
|
if (!socket.write(bytes)) upstream.pause();
|
|
});
|
|
socket.on('drain', () => upstream.resume());
|
|
socket.on('error', close); upstream.on('error', close);
|
|
socket.on('close', close); upstream.on('close', close);
|
|
});
|
|
server.maxConnections = MAX_PROXY_CONNECTIONS;
|
|
await new Promise((resolve, reject) => {
|
|
const fail = error => { server.off('listening', resolve); reject(error); };
|
|
server.once('error', fail);
|
|
server.listen(0, '127.0.0.1', () => { server.off('error', fail); resolve(); });
|
|
});
|
|
return {
|
|
server,
|
|
port: server.address().port,
|
|
close: async () => {
|
|
for (const socket of sockets) socket.destroy();
|
|
await new Promise(resolve => server.close(() => resolve()));
|
|
},
|
|
};
|
|
}
|