@@ -71,6 +71,23 @@ let plotWatcher: FSWatcher;
7171let activeBrowserPanel : WebviewPanel | undefined ;
7272let activeBrowserUri : Uri | undefined ;
7373let activeBrowserExternalUri : Uri | undefined ;
74+ let incomingRequestServerAddressInfo : AddressInfo | undefined = undefined ;
75+ let attached = false ;
76+
77+ const addressToStr = ( addressInfo : AddressInfo ) => `${ addressInfo . address } :${ addressInfo . port } ` ;
78+
79+ function updateSessionStatusBarItem ( sessionStatusBarItem : StatusBarItem ) {
80+ const addressInfoStr = incomingRequestServerAddressInfo && addressToStr ( incomingRequestServerAddressInfo ) ;
81+ if ( attached ) {
82+ sessionStatusBarItem . text = `R ${ rVer } : ${ pid } ` + ( addressInfoStr ? ` (Connected via ${ addressInfoStr } )` : '' ) ;
83+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions, @typescript-eslint/no-unsafe-member-access
84+ sessionStatusBarItem . tooltip = `${ info ?. version } \nProcess ID: ${ pid } \n${ addressInfoStr ? ( `Connected via TCP address: ${ addressInfoStr } \n` ) : '' } Command: ${ info ?. command } \nStart time: ${ info ?. start_time } \nClick to attach to active terminal.` ;
85+ } else {
86+ sessionStatusBarItem . text = `R: (not attached${ addressInfoStr ? `, listening on ${ addressInfoStr } ` : '' } )` ;
87+ sessionStatusBarItem . tooltip = 'Click to attach active terminal.' ; // TODO: Make clicking be aware of TCP R connections
88+ }
89+ sessionStatusBarItem . show ( ) ;
90+ }
7491
7592export function deploySessionWatcher ( extensionPath : string ) : void {
7693 console . info ( `[deploySessionWatcher] extensionPath: ${ extensionPath } ` ) ;
@@ -792,52 +809,62 @@ async function updateRequest(sessionStatusBarItem: StatusBarItem) {
792809
793810function startIncomingRequestServer ( ip : string , sessionStatusBarItem : StatusBarItem ) {
794811 const incomingRequestServer = new Server ( async ( socket : Socket ) => {
812+ console . info ( `Incoming connection to the request server from ${ addressToStr ( socket . address ( ) as AddressInfo ) } ` )
795813 if ( incomingRequestServerConnected ) {
796- // TODO: Add some details (ip+port) of the incoming connection
797814 console . error ( 'A new connection to the incoming request server tries to connect but another connection currently connected!' ) ;
798815 return ;
799816 }
800817
801818 console . info ( 'A new connection to the incoming request server has been established.' ) ;
802819 incomingRequestServerConnected = true ;
803- // TODO: Handle correct status bar update
804-
805- const promiseSocket = new PromiseSocket ( socket ) ;
806-
807- console . info ( "Waiting for TCP input..." )
808-
809- // TODO: Handle Exceptions
810- let contentToProcess = "" ;
811- while ( true ) {
812- const currentChunk = await promiseSocket . read ( ) ;
813- if ( currentChunk === undefined ) {
814- console . info ( "Incoming request server socket EOF" )
815- // The end of the socket
816-
817- // TODO: Verify a correct detach!
818- // TODO: Verify that `contentToProcess` is empty!
819- incomingRequestServerConnected = false ;
820- return ;
821- }
822- // otherwise
823-
824- contentToProcess = contentToProcess + currentChunk ;
825-
826- const requests = contentToProcess . split ( ( / \r ? \n / ) ) ;
827- for ( let i = 0 ; i < requests . length - 1 ; ++ i ) {
828- const requestContent = requests [ i ] ;
829-
830- //console.debug(`TCP Request received from client: ${requestContent}.`);
831- const request = JSON . parse ( requestContent ) as ISessionRequest ;
832- await processRequest ( request , socket , sessionStatusBarItem ) ;
820+
821+ try {
822+ const promiseSocket = new PromiseSocket ( socket ) ;
823+ console . info ( "Waiting for TCP input..." )
824+
825+ let contentToProcess = "" ;
826+ while ( true ) {
827+ const currentChunk = await promiseSocket . read ( ) ;
828+ if ( currentChunk === undefined ) {
829+ // The end of the socket
830+ console . info ( "Incoming request server socket EOF" ) ;
831+
832+ // Force cleaning even if somehow not detached
833+ await cleanupSession ( ) ;
834+
835+ if ( contentToProcess ) {
836+ console . error ( "TCP connection recieved EOF, but the last content didn't end up with line break." )
837+ }
838+ incomingRequestServerConnected = false ;
839+ return ;
840+ }
841+ // otherwise
842+
843+ contentToProcess = contentToProcess + currentChunk ;
844+
845+ const requests = contentToProcess . split ( ( / \r ? \n / ) ) ;
846+ for ( let i = 0 ; i < requests . length - 1 ; ++ i ) {
847+ const requestContent = requests [ i ] ;
848+
849+ //console.debug(`TCP Request received from client: ${requestContent}.`);
850+ const request = JSON . parse ( requestContent ) as ISessionRequest ;
851+ await processRequest ( request , socket , sessionStatusBarItem ) ;
852+ }
853+ contentToProcess = requests [ requests . length - 1 ] ;
833854 }
834- contentToProcess = requests [ requests . length - 1 ] ;
855+ } catch ( err ) {
856+ console . error ( `Error while processing TCP connection: ${ err } ` ) ;
857+
858+ await cleanupSession ( ) ;
859+ incomingRequestServerConnected = false ;
835860 }
836861 } ) ;
837862
838863 const server = incomingRequestServer . listen ( 0 , ip , function ( ) {
839- const addressInfo = server . address ( ) as AddressInfo ;
840- console . info ( `Started listening on ${ addressInfo . address } :${ addressInfo . port } ` ) ;
864+ incomingRequestServerAddressInfo = server . address ( ) as AddressInfo ;
865+ console . info ( `Started listening on ${ addressToStr ( incomingRequestServerAddressInfo ) } ` ) ;
866+
867+ updateSessionStatusBarItem ( sessionStatusBarItem ) ;
841868 } ) ;
842869
843870 return server ;
@@ -885,16 +912,15 @@ export async function processRequest(request: ISessionRequest, socket: Socket |
885912 if ( ! request . tempdir || ! request . wd ) {
886913 return ;
887914 }
915+ attached = true ;
888916 rVer = String ( request . version ) ;
889917 pid = String ( request . pid ) ;
890918 info = request . info ;
891919 sessionDir = path . join ( request . tempdir , 'vscode-R' ) ;
892920 workingDir = request . wd ;
921+ // TODO: Log and show correct TCP info here
893922 console . info ( `[updateRequest] attach PID: ${ pid } ` ) ;
894- sessionStatusBarItem . text = `R ${ rVer } : ${ pid } ` ;
895- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions, @typescript-eslint/no-unsafe-member-access
896- sessionStatusBarItem . tooltip = `${ info ?. version } \nProcess ID: ${ pid } \nCommand: ${ info ?. command } \nStart time: ${ info ?. start_time } \nClick to attach to active terminal.` ;
897- sessionStatusBarItem . show ( ) ;
923+ updateSessionStatusBarItem ( sessionStatusBarItem ) ;
898924 if ( socket == null ) {
899925 updateSessionWatcher ( ) ;
900926 }
@@ -915,9 +941,13 @@ export async function processRequest(request: ISessionRequest, socket: Socket |
915941 }
916942 break ;
917943 }
918- case 'detach' : { // Only on filesystem based session?
919- if ( request . pid ) {
920- await cleanupSession ( request . pid ) ;
944+ case 'detach' : {
945+ if ( socket == null ) {
946+ if ( request . pid ) {
947+ await cleanupSession ( request . pid ) ;
948+ }
949+ } else {
950+ await cleanupSession ( ) ;
921951 }
922952 break ;
923953 }
@@ -963,11 +993,11 @@ export async function processRequest(request: ISessionRequest, socket: Socket |
963993 }
964994}
965995
966- export async function cleanupSession ( pidArg : string ) : Promise < void > {
967- if ( pid === pidArg ) {
996+ export async function cleanupSession ( pidArg ?: string ) : Promise < void > {
997+ if ( pidArg === undefined || pid === pidArg ) {
998+ attached = false ;
968999 if ( sessionStatusBarItem ) {
969- sessionStatusBarItem . text = 'R: (not attached)' ;
970- sessionStatusBarItem . tooltip = 'Click to attach active terminal.' ;
1000+ updateSessionStatusBarItem ( sessionStatusBarItem ) ;
9711001 }
9721002 server = undefined ;
9731003 workspaceData . globalenv = { } ;
0 commit comments