protected override async Task <CommandProcessorThread> ConnectAsync(CancellationToken ct) { var remoteProcess = _process as PythonRemoteProcess; try { _serviceProvider.GetPythonToolsService().Logger.LogEvent(Logging.PythonLogEvent.DebugRepl, new Logging.DebugReplInfo { RemoteProcess = remoteProcess != null, Version = _process.LanguageVersion.ToVersion().ToString() }); } catch (Exception ex) { Debug.Fail(ex.ToUnhandledExceptionMessage(GetType())); } if (remoteProcess == null) { var conn = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); conn.Bind(new IPEndPoint(IPAddress.Loopback, 0)); conn.Listen(0); var portNum = ((IPEndPoint)conn.LocalEndPoint).Port; var proc = System.Diagnostics.Process.GetProcessById(_process.Id); var thread = CommandProcessorThread.Create(this, conn, proc); await _process.ConnectReplAsync(portNum); return(thread); } // Ignore SSL errors, since user was already prompted about them and chose to ignore them when he attached to this process. using (var debugConn = await remoteProcess.ConnectAsync(false, ct)) { // After the REPL attach response is received, we go from // using the debugger protocol to the REPL protocol. // It's important to have a clean break between the 2, and at the right time. // The server will send the debugger protocol response for attach // before sending anything else and as soon as we read that // response, we stop reading any more messages. // Then we give the stream to the REPL protocol handler. try { var response = await debugConn.SendRequestAsync(new LDP.RemoteReplAttachRequest(), ct, resp => { Debug.WriteLine("Stopping debug connection message processing. Switching from debugger protocol to REPL protocol."); // This causes the message handling loop to exit throw new OperationCanceledException(); }); if (!response.accepted) { WriteError(Strings.ConnErrorMessages_RemoteAttachRejected); return(null); } // Get the stream out of the connection before Dispose is called, // so that the stream doesn't get closed. var stream = debugConn.DetachStream(); return(CommandProcessorThread.Create(this, stream)); } catch (FailedRequestException ex) { WriteError(ex.Message); return(null); } } }