예제 #1
0
        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);
                }
            }
        }