import * as vscode from "vscode" ; import * as Net from "net" ; import { CordovaDebugSession } from "../debugger/cordovaDebugSession" ; import { CordovaSession , CordovaSessionStatus } from "../debugger/debugSessionWrapper" ; export class CordovaSessionManager implements vscode . DebugAdapterDescriptorFactory { protected readonly cordovaDebuggingFlag = "isCordovaDebugging" ; private servers = new Map < string , Net . Server > ( ) ; private connections = new Map < string , Net . Socket > ( ) ; private cordovaDebugSessions = new Map < string , CordovaSession > ( ) ; private restartingVSCodeSessions = new Set < string > ( ) ; public createDebugAdapterDescriptor ( session , executable ) { const cordovaSession = this . createCordovaSession ( session ) ; this . cordovaDebugSessions . set ( cordovaSession . getSessionId ( ) , cordovaSession ) ; vscode . commands . executeCommand ( "setContext" , this . cordovaDebuggingFlag , true ) ; const debugServer = Net . createServer ( socket => { let cordovaDebugSession = new CordovaDebugSession ( cordovaSession , this ) ; cordovaDebugSession . setRunAsServer ( true ) ; this . connections . set ( cordovaSession . getSessionId ( ) , socket ) ; cordovaDebugSession . start ( < NodeJS . ReadableStream > socket , socket ) ; } ) ; debugServer . listen ( 0 ) ; this . servers . set ( cordovaSession . getSessionId ( ) , debugServer ) ; return new vscode . DebugAdapterServer ( ( < Net . AddressInfo > debugServer . address ( ) ) . port ) ; } public terminate ( cordovaDebugSessionId , restart = false , forcedStop = false ) { if ( restart && this . cordovaDebugSessions . has ( cordovaDebugSessionId ) ) { this . restartingVSCodeSessions . add ( this . cordovaDebugSessions . get ( cordovaDebugSessionId ) . getVSCodeDebugSession ( ) . id ) ; } this . cordovaDebugSessions . delete ( cordovaDebugSessionId ) ; if ( this . cordovaDebugSessions . size === 0 ) { vscode . commands . executeCommand ( "setContext" , this . cordovaDebuggingFlag , false ) ; } this . destroyServer ( cordovaDebugSessionId , this . servers . get ( cordovaDebugSessionId ) ) ; let connection = this . connections . get ( cordovaDebugSessionId ) ; if ( connection ) { if ( forcedStop ) { this . destroySocketConnection ( connection ) ; } this . connections . delete ( cordovaDebugSessionId ) ; } } public getCordovaDebugSessionByProjectRoot ( projectRoot ) { for ( let cordovaSession of this . cordovaDebugSessions . values ( ) ) { if ( cordovaSession . getVSCodeDebugSession ( ) . workspaceFolder . uri . fsPath === projectRoot ) { return cordovaSession ; } } return null ; } public dispose ( ) { this . servers . forEach ( ( server , key ) => { this . destroyServer ( key , server ) ; } ) ; this . connections . forEach ( ( conn , key ) => { this . destroySocketConnection ( conn ) ; this . connections . delete ( key ) ; } ) ; } private createCordovaSession ( session ) { let cordovaSession = new CordovaSession ( session ) ; if ( this . restartingVSCodeSessions . has ( session . id ) ) { cordovaSession . setStatus ( CordovaSessionStatus . Pending ) ; this . restartingVSCodeSessions . delete ( session . id ) ; } return cordovaSession ; } private destroyServer ( cordovaDebugSessionId , server ? ) { if ( server ) { server . close ( ) ; this . servers . delete ( cordovaDebugSessionId ) ; } } private destroySocketConnection ( conn ) { conn . removeAllListeners ( ) ; conn . on ( "error" , ( ) => undefined ) ; conn . destroy ( ) ; } }