Exemplo n.º 1
0
 public PythonRemoteDebugProcess(PythonRemoteDebugPort port, int pid, string exe, string username, string version) {
     this._port = port;
     this._pid = (pid == 0) ? 1 : pid; // attach dialog won't show processes with pid==0
     this._username = username;
     this._exe = string.IsNullOrEmpty(exe) ? "<python>" : exe;
     this._version = version;
 }
Exemplo n.º 2
0
 public PythonRemoteDebugProcess(PythonRemoteDebugPort port, int pid, string exe, string username, string version)
 {
     this._port     = port;
     this._pid      = (pid == 0) ? 1 : pid; // attach dialog won't show processes with pid==0
     this._username = username;
     this._exe      = string.IsNullOrEmpty(exe) ? "<python>" : exe;
     this._version  = version;
 }
        // Qualifier for our transport has one of the following formats:
        //
        //   tcp[s]://[secret@]hostname[:port]
        //   ws[s]://[secret@]hostname[:port][/path]
        //   [secret@]hostname[:port]
        //
        // 'tcp' and 'tcps' are for connecting directly to ptvsd; 'ws' and 'wss' are for connecting through WebSocketProxy.
        // The versions ending with '...s' use SSL to secure the connection. If no scheme is specified, 'tcp' is the default.
        // If port is not specified, it defaults to 5678 for 'tcp' and 'tcps', 80 for 'ws' and 443 for 'wss'.
        public int AddPort(IDebugPortRequest2 pRequest, out IDebugPort2 ppPort)
        {
            ppPort = null;

            string name;

            pRequest.GetPortName(out name);

            // Support old-style 'hostname:port' format, as well.
            if (!name.Contains("://"))
            {
                name = "tcp://" + name;
            }

            var uri       = new Uri(name, UriKind.Absolute);
            var transport = DebuggerTransportFactory.Get(uri);

            if (transport == null)
            {
                MessageBox.Show(
                    Strings.RemoteUnrecognizedDebuggingTransport.FormatUI(uri.Scheme),
                    Strings.ProductTitle,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error
                    );
                return(VSConstants.E_FAIL);
            }

            var validationError = transport.Validate(uri);

            if (validationError != null)
            {
                return(validationError.HResult);
            }

            var port = new PythonRemoteDebugPort(this, pRequest, uri, DebugLog);

            if (PythonDebugOptionsServiceHelper.Options.UseLegacyDebugger)
            {
                // Validate connection early. Debugger automation (DTE) objects are not consistent in error checking from this
                // point on, so errors reported from EnumProcesses and further calls may be ignored and treated as successes
                // (with empty result). Reporting an error here works around that.
                int hr = port.EnumProcesses(out IEnumDebugProcesses2 processes);
                if (hr < 0)
                {
                    return(hr);
                }
            }

            ppPort = port;
            _ports.Add(port);

            return(VSConstants.S_OK);
        }
Exemplo n.º 4
0
        // Qualifier for our transport has one of the following formats:
        //
        //   tcp[s]://[secret@]hostname[:port]
        //   ws[s]://[secret@]hostname[:port][/path]
        //   [secret@]hostname[:port]
        //
        // 'tcp' and 'tcps' are for connecting directly to ptvsd; 'ws' and 'wss' are for connecting through WebSocketProxy.
        // The versions ending with '...s' use SSL to secure the connection. If no scheme is specified, 'tcp' is the default.
        // If port is not specified, it defaults to 5678 for 'tcp' and 'tcps', 80 for 'ws' and 443 for 'wss'.
        public int AddPort(IDebugPortRequest2 pRequest, out IDebugPort2 ppPort)
        {
            ppPort = null;

            string name;

            pRequest.GetPortName(out name);

            // Support old-style 'hostname:port' format, as well.
            if (!name.Contains("://"))
            {
                name = "tcp://" + name;
            }

            var uri       = new Uri(name, UriKind.Absolute);
            var transport = DebuggerTransportFactory.Get(uri);

            if (transport == null)
            {
                MessageBox.Show(
                    Strings.RemoteUnrecognizedDebuggingTransport.FormatUI(uri.Scheme),
                    Strings.ProductTitle,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error
                    );
                return(VSConstants.E_FAIL);
            }

            var validationError = transport.Validate(uri);

            if (validationError != null)
            {
                return(validationError.HResult);
            }

            var port = new PythonRemoteDebugPort(this, pRequest, uri, DebugLog);

            ppPort = port;
            _ports.Add(port);

            return(VSConstants.S_OK);
        }
Exemplo n.º 5
0
        // Qualifier for our transport has one of the following formats:
        //
        //   tcp[s]://[secret@]hostname[:port]
        //   ws[s]://[secret@]hostname[:port][/path]
        //   [secret@]hostname[:port]
        //
        // 'tcp' and 'tcps' are for connecting directly to ptvsd; 'ws' and 'wss' are for connecting through WebSocketProxy.
        // The versions ending with '...s' use SSL to secure the connection. If no scheme is specified, 'tcp' is the default.
        // If port is not specified, it defaults to 5678 for 'tcp' and 'tcps', 80 for 'ws' and 443 for 'wss'.
        public int AddPort(IDebugPortRequest2 pRequest, out IDebugPort2 ppPort) {
            ppPort = null;

            string name;
            pRequest.GetPortName(out name);

            // Support old-style 'hostname:port' format, as well.
            if (!name.Contains("://")) {
                name = "tcp://" + name;
            }

            var uri = new Uri(name, UriKind.Absolute);
            var transport = DebuggerTransportFactory.Get(uri);
            if (transport == null) {
                MessageBox.Show(string.Format("Unrecognized remote debugging transport '{0}'.", uri.Scheme), null, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return VSConstants.E_FAIL;
            }

            var validationError = transport.Validate(uri);
            if (validationError != null) {
                return validationError.HResult;
            }

            var port = new PythonRemoteDebugPort(this, pRequest, uri);

            // Validate connection early. Debugger automation (DTE) objects are not consistent in error checking from this
            // point on, so errors reported from EnumProcesses and further calls may be ignored and treated as successes
            // (with empty result). Reporting an error here works around that.
            IEnumDebugProcesses2 processes;
            int hr = port.EnumProcesses(out processes);
            if (hr < 0) {
                return hr;
            }

            ppPort = port;
            return VSConstants.S_OK;
        }
Exemplo n.º 6
0
        public static PythonRemoteDebugProcess Connect(PythonRemoteDebugPort port)
        {
            PythonRemoteDebugProcess process = null;

            // Connect to the remote debugging server and obtain process information. If any errors occur, display an error dialog, and keep
            // trying for as long as user clicks "Retry".
            while (true)
            {
                Stream stream = null;
                ConnectionException connEx = null;
                try {
                    // Process information is not sensitive, so ignore any SSL certificate errors, rather than bugging the user with warning dialogs.
                    stream = PythonRemoteProcess.Connect(port.Uri, false);
                } catch (ConnectionException ex) {
                    connEx = ex;
                }

                using (stream) {
                    if (stream != null)
                    {
                        try {
                            stream.Write(PythonRemoteProcess.InfoCommandBytes);
                            int    pid      = stream.ReadInt32();
                            string exe      = stream.ReadString();
                            string username = stream.ReadString();
                            string version  = stream.ReadString();
                            process = new PythonRemoteDebugProcess(port, pid, exe, username, version);
                            break;
                        } catch (IOException ex) {
                            connEx = new ConnectionException(ConnErrorMessages.RemoteNetworkError, ex);
                        }
                    }

                    if (connEx != null)
                    {
                        string errText;
                        switch (connEx.Error)
                        {
                        case ConnErrorMessages.RemoteUnsupportedServer:
                            errText = string.Format("Remote server at {0} is not a Python Tools for Visual Studio remote debugging server, or its version is not supported.", port.Uri);
                            break;

                        case ConnErrorMessages.RemoteSecretMismatch:
                            errText = string.Format("Secret '{0}' did not match the server secret at {1}. Make sure that the secret is specified correctly in the Qualifier textbox, e.g. tcp://secret@localhost.",
                                                    port.Uri.UserInfo, new UriBuilder(port.Uri)
                            {
                                UserName = null, Password = null
                            }.Uri);
                            break;

                        case ConnErrorMessages.RemoteSslError:
                            // User has already got a warning dialog and clicked "Cancel" on that, so no further prompts are needed.
                            return(null);

                        default:
                        {
                            // Azure uses HTTP 503 (Service Unavailable) to indicate that websocket connections are not supported. Show a special error message for that.
                            var wsEx = connEx.InnerException as WebSocketException;
                            if (wsEx != null)
                            {
                                var webEx = wsEx.InnerException as WebException;
                                if (webEx != null)
                                {
                                    var httpResponse = webEx.Response as HttpWebResponse;
                                    if (httpResponse != null && httpResponse.StatusCode == HttpStatusCode.ServiceUnavailable)
                                    {
                                        errText = string.Format("Could not connect to remote Python process at {0}. Make sure that web sockets are enabled for the corresponding web site in Azure portal.", port.Uri);
                                        break;
                                    }
                                }
                            }

                            errText = string.Format("Could not connect to remote Python process at {0}. Make sure that the process is running, and has called ptvsd.enable_attach().", port.Uri);
                            for (var ex = connEx.InnerException; ex != null; ex = ex.InnerException)
                            {
                                if (ex.InnerException == null)
                                {
                                    errText += "\r\n\r\nAdditional information:\r\n" + ex.Message;
                                }
                            }
                            break;
                        }
                        }

                        DialogResult dlgRes = MessageBox.Show(errText, null, MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
                        if (dlgRes != DialogResult.Retry)
                        {
                            break;
                        }
                    }
                }
            }

            return(process);
        }
Exemplo n.º 7
0
        public static PythonRemoteDebugProcess Connect(PythonRemoteDebugPort port) {
            PythonRemoteDebugProcess process = null;

            // Connect to the remote debugging server and obtain process information. If any errors occur, display an error dialog, and keep
            // trying for as long as user clicks "Retry".
            while (true) {
                Stream stream = null;
                ConnectionException connEx = null;
                try {
                    // Process information is not sensitive, so ignore any SSL certificate errors, rather than bugging the user with warning dialogs.
                    stream = PythonRemoteProcess.Connect(port.Uri, false);
                } catch (ConnectionException ex) {
                    connEx = ex;
                }

                using (stream) {
                    if (stream != null) {
                        try {
                            stream.Write(PythonRemoteProcess.InfoCommandBytes);
                            int pid = stream.ReadInt32();
                            string exe = stream.ReadString();
                            string username = stream.ReadString();
                            string version = stream.ReadString();
                            process = new PythonRemoteDebugProcess(port, pid, exe, username, version);
                            break;
                        } catch (IOException ex) {
                            connEx = new ConnectionException(ConnErrorMessages.RemoteNetworkError, ex);
                        }
                    }

                    if (connEx != null) {
                        string errText;
                        switch (connEx.Error) {
                            case ConnErrorMessages.RemoteUnsupportedServer:
                                errText = string.Format("Remote server at {0} is not a Python Tools for Visual Studio remote debugging server, or its version is not supported.", port.Uri);
                                break;
                            case ConnErrorMessages.RemoteSecretMismatch:
                                errText = string.Format("Secret '{0}' did not match the server secret at {1}. Make sure that the secret is specified correctly in the Qualifier textbox, e.g. tcp://secret@localhost.",
                                    port.Uri.UserInfo, new UriBuilder(port.Uri) { UserName = null, Password = null }.Uri);
                                break;
                            case ConnErrorMessages.RemoteSslError:
                                // User has already got a warning dialog and clicked "Cancel" on that, so no further prompts are needed.
                                return null;
                            default:
                                {
                                    // Azure uses HTTP 503 (Service Unavailable) to indicate that websocket connections are not supported. Show a special error message for that.
                                    var wsEx = connEx.InnerException as WebSocketException;
                                    if (wsEx != null) {
                                        var webEx = wsEx.InnerException as WebException;
                                        if (webEx != null) {
                                            var httpResponse = webEx.Response as HttpWebResponse;
                                            if (httpResponse != null && httpResponse.StatusCode == HttpStatusCode.ServiceUnavailable) {
                                                errText = string.Format("Could not connect to remote Python process at {0}. Make sure that web sockets are enabled for the corresponding web site in Azure portal.", port.Uri);
                                                break;
                                            }
                                        }
                                    }

                                    errText = string.Format("Could not connect to remote Python process at {0}. Make sure that the process is running, and has called ptvsd.enable_attach().", port.Uri);
                                    for (var ex = connEx.InnerException; ex != null; ex = ex.InnerException) {
                                        if (ex.InnerException == null) {
                                            errText += "\r\n\r\nAdditional information:\r\n" + ex.Message;
                                        }
                                    }
                                    break;
                                }
                        }

                        DialogResult dlgRes = MessageBox.Show(errText, null, MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
                        if (dlgRes != DialogResult.Retry) {
                            break;
                        }
                    }
                }
            }

            return process;
        }
Exemplo n.º 8
0
        public static async Task <PythonRemoteDebugProcess> ConnectAsync(PythonRemoteDebugPort port, TextWriter debugLog, CancellationToken ct)
        {
            PythonRemoteDebugProcess process = null;

            // Connect to the remote debugging server and obtain process information. If any errors occur, display an error dialog, and keep
            // trying for as long as user clicks "Retry".
            while (true)
            {
                DebugConnection     debugConn = null;
                ConnectionException connEx    = null;
                try {
                    // Process information is not sensitive, so ignore any SSL certificate errors, rather than bugging the user with warning dialogs.
                    debugConn = await PythonRemoteProcess.ConnectAsync(port.Uri, false, debugLog, ct);
                } catch (ConnectionException ex) {
                    connEx = ex;
                }

                using (debugConn) {
                    if (debugConn != null)
                    {
                        try {
                            var response = await debugConn.SendRequestAsync(new LDP.RemoteDebuggerInfoRequest(), ct);

                            process = new PythonRemoteDebugProcess(port, response.processId, response.executable, response.user, response.pythonVersion);
                            break;
                        } catch (IOException ex) {
                            connEx = new ConnectionException(ConnErrorMessages.RemoteNetworkError, ex);
                        } catch (FailedRequestException ex) {
                            connEx = new ConnectionException(ConnErrorMessages.RemoteNetworkError, ex);
                        }
                    }

                    if (connEx != null)
                    {
                        string errText;
                        switch (connEx.Error)
                        {
                        case ConnErrorMessages.RemoteUnsupportedServer:
                            errText = Strings.RemoteUnsupportedServer_Host.FormatUI(port.Uri);
                            break;

                        case ConnErrorMessages.RemoteSecretMismatch:
                            errText = Strings.RemoteSecretMismatch_Host.FormatUI(new UriBuilder(port.Uri)
                            {
                                UserName = null, Password = null
                            }.Uri);
                            break;

                        case ConnErrorMessages.RemoteSslError:
                            // User has already got a warning dialog and clicked "Cancel" on that, so no further prompts are needed.
                            return(null);

                        default:
                        {
                            // Azure uses HTTP 503 (Service Unavailable) to indicate that websocket connections are not supported. Show a special error message for that.
                            var wsEx = connEx.InnerException as WebSocketException;
                            if (wsEx != null)
                            {
                                var webEx = wsEx.InnerException as WebException;
                                if (webEx != null)
                                {
                                    var httpResponse = webEx.Response as HttpWebResponse;
                                    if (httpResponse != null && httpResponse.StatusCode == HttpStatusCode.ServiceUnavailable)
                                    {
                                        errText = Strings.RemoteAzureServiceUnavailable_Host.FormatUI(port.Uri);
                                        break;
                                    }
                                }
                            }

                            errText = Strings.RemoteServiceUnavailable_Host.FormatUI(port.Uri);
                            for (var ex = connEx.InnerException; ex != null; ex = ex.InnerException)
                            {
                                if (ex.InnerException == null)
                                {
                                    errText += "\r\n\r\n{0}\r\n{1}".FormatUI(Strings.AdditionalInformation, ex.Message);
                                }
                            }
                            break;
                        }
                        }

                        DialogResult dlgRes = MessageBox.Show(errText, Strings.ProductTitle, MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
                        if (dlgRes != DialogResult.Retry)
                        {
                            break;
                        }
                    }
                }
            }

            return(process);
        }
Exemplo n.º 9
0
        public static PythonRemoteDebugProcess Connect(PythonRemoteDebugPort port)
        {
            PythonRemoteDebugProcess process = null;

            // Connect to the remote debugging server and obtain process information. If any errors occur, display an error dialog, and keep
            // trying for as long as user clicks "Retry".
            while (true)
            {
                Stream stream = null;
                ConnectionException connEx = null;
                try {
                    // Process information is not sensitive, so ignore any SSL certificate errors, rather than bugging the user with warning dialogs.
                    stream = PythonRemoteProcess.Connect(port.Uri, false);
                } catch (ConnectionException ex) {
                    connEx = ex;
                }

                using (stream) {
                    if (stream != null)
                    {
                        try {
                            stream.Write(PythonRemoteProcess.InfoCommandBytes);
                            int    pid      = stream.ReadInt32();
                            string exe      = stream.ReadString();
                            string username = stream.ReadString();
                            string version  = stream.ReadString();
                            process = new PythonRemoteDebugProcess(port, pid, exe, username, version);
                            break;
                        } catch (IOException ex) {
                            connEx = new ConnectionException(ConnErrorMessages.RemoteNetworkError, ex);
                        }
                    }

                    if (connEx != null)
                    {
                        string errText;
                        switch (connEx.Error)
                        {
                        case ConnErrorMessages.RemoteUnsupportedServer:
                            errText = Strings.RemoteUnsupportedServer_Host.FormatUI(port.Uri);
                            break;

                        case ConnErrorMessages.RemoteSecretMismatch:
                            errText = Strings.RemoteSecretMismatch_Host.FormatUI(new UriBuilder(port.Uri)
                            {
                                UserName = null, Password = null
                            }.Uri);
                            break;

                        case ConnErrorMessages.RemoteSslError:
                            // User has already got a warning dialog and clicked "Cancel" on that, so no further prompts are needed.
                            return(null);

                        default:
                        {
                            // Azure uses HTTP 503 (Service Unavailable) to indicate that websocket connections are not supported. Show a special error message for that.
                            var wsEx = connEx.InnerException as WebSocketException;
                            if (wsEx != null)
                            {
                                var webEx = wsEx.InnerException as WebException;
                                if (webEx != null)
                                {
                                    var httpResponse = webEx.Response as HttpWebResponse;
                                    if (httpResponse != null && httpResponse.StatusCode == HttpStatusCode.ServiceUnavailable)
                                    {
                                        errText = Strings.RemoteAzureServiceUnavailable_Host.FormatUI(port.Uri);
                                        break;
                                    }
                                }
                            }

                            errText = Strings.RemoteServiceUnavailable_Host.FormatUI(port.Uri);
                            for (var ex = connEx.InnerException; ex != null; ex = ex.InnerException)
                            {
                                if (ex.InnerException == null)
                                {
                                    errText += "\r\n\r\n{0}\r\n{1}".FormatUI(Strings.AdditionalInformation, ex.Message);
                                }
                            }
                            break;
                        }
                        }

                        DialogResult dlgRes = MessageBox.Show(errText, Strings.ProductTitle, MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
                        if (dlgRes != DialogResult.Retry)
                        {
                            break;
                        }
                    }
                }
            }

            return(process);
        }
Exemplo n.º 10
0
        public static PythonRemoteDebugProcess Connect(PythonRemoteDebugPort port) {
            PythonRemoteDebugProcess process = null;

            // Connect to the remote debugging server and obtain process information. If any errors occur, display an error dialog, and keep
            // trying for as long as user clicks "Retry".
            while (true) {
                Stream stream = null;
                ConnectionException connEx = null;
                try {
                    // Process information is not sensitive, so ignore any SSL certificate errors, rather than bugging the user with warning dialogs.
                    stream = PythonRemoteProcess.Connect(port.Uri, false);
                } catch (ConnectionException ex) {
                    connEx = ex;
                }

                using (stream) {
                    if (stream != null) {
                        try {
                            stream.Write(PythonRemoteProcess.InfoCommandBytes);
                            int pid = stream.ReadInt32();
                            string exe = stream.ReadString();
                            string username = stream.ReadString();
                            string version = stream.ReadString();
                            process = new PythonRemoteDebugProcess(port, pid, exe, username, version);
                            break;
                        } catch (IOException ex) {
                            connEx = new ConnectionException(ConnErrorMessages.RemoteNetworkError, ex);
                        }
                    }

                    if (connEx != null) {
                        string errText;
                        switch (connEx.Error) {
                            case ConnErrorMessages.RemoteUnsupportedServer:
                                errText = Strings.RemoteUnsupportedServer_Host.FormatUI(port.Uri);
                                break;
                            case ConnErrorMessages.RemoteSecretMismatch:
                                errText = Strings.RemoteSecretMismatch_Host.FormatUI(new UriBuilder(port.Uri) { UserName = null, Password = null }.Uri);
                                break;
                            case ConnErrorMessages.RemoteSslError:
                                // User has already got a warning dialog and clicked "Cancel" on that, so no further prompts are needed.
                                return null;
                            default:
                                {
                                    // Azure uses HTTP 503 (Service Unavailable) to indicate that websocket connections are not supported. Show a special error message for that.
                                    var wsEx = connEx.InnerException as WebSocketException;
                                    if (wsEx != null) {
                                        var webEx = wsEx.InnerException as WebException;
                                        if (webEx != null) {
                                            var httpResponse = webEx.Response as HttpWebResponse;
                                            if (httpResponse != null && httpResponse.StatusCode == HttpStatusCode.ServiceUnavailable) {
                                                errText = Strings.RemoteAzureServiceUnavailable_Host.FormatUI(port.Uri);
                                                break;
                                            }
                                        }
                                    }

                                    errText = Strings.RemoteServiceUnavailable_Host.FormatUI(port.Uri);
                                    for (var ex = connEx.InnerException; ex != null; ex = ex.InnerException) {
                                        if (ex.InnerException == null) {
                                            errText += "\r\n\r\n{0}\r\n{1}".FormatUI(Strings.AdditionalInformation, ex.Message);
                                        }
                                    }
                                    break;
                                }
                        }

                        DialogResult dlgRes = MessageBox.Show(errText, null, MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
                        if (dlgRes != DialogResult.Retry) {
                            break;
                        }
                    }
                }
            }

            return process;
        }