1import * as Log from '../../../log'; 2import { installExitHooks } from '../../../utils/exit'; 3import { adbArgs, Device, getAttachedDevicesAsync, getServer, logUnauthorized } from './adb'; 4 5let removeExitHook: (() => void) | null = null; 6 7export async function startAdbReverseAsync(ports: number[]): Promise<boolean> { 8 // Install cleanup automatically... 9 removeExitHook = installExitHooks(() => { 10 stopAdbReverseAsync(ports); 11 }); 12 13 const devices = await getAttachedDevicesAsync(); 14 for (const device of devices) { 15 for (const port of ports) { 16 if (!(await adbReverseAsync(device, port))) { 17 Log.debug(`[ADB] Failed to start reverse port ${port} on device "${device.name}"`); 18 return false; 19 } 20 } 21 } 22 return true; 23} 24 25export async function stopAdbReverseAsync(ports: number[]): Promise<void> { 26 removeExitHook?.(); 27 28 const devices = await getAttachedDevicesAsync(); 29 for (const device of devices) { 30 for (const port of ports) { 31 await adbReverseRemoveAsync(device, port); 32 } 33 } 34} 35 36async function adbReverseAsync(device: Device, port: number): Promise<boolean> { 37 if (!device.isAuthorized) { 38 logUnauthorized(device); 39 return false; 40 } 41 42 try { 43 await getServer().runAsync(adbArgs(device.pid, 'reverse', `tcp:${port}`, `tcp:${port}`)); 44 return true; 45 } catch (error: any) { 46 Log.warn(`[ADB] Couldn't reverse port ${port}: ${error.message}`); 47 return false; 48 } 49} 50 51async function adbReverseRemoveAsync(device: Device, port: number): Promise<boolean> { 52 if (!device.isAuthorized) { 53 return false; 54 } 55 56 try { 57 await getServer().runAsync(adbArgs(device.pid, 'reverse', '--remove', `tcp:${port}`)); 58 return true; 59 } catch (error: any) { 60 // Don't send this to warn because we call this preemptively sometimes 61 Log.debug(`[ADB] Couldn't reverse remove port ${port}: ${error.message}`); 62 return false; 63 } 64} 65