Esempio n. 1
0
#pragma warning restore CA1710 // Identifiers should have correct suffix

        private SolidityDebugger(IDebuggerTransport debuggerTransport, bool useContractsSubDir)
        {
            _debuggerTransport = debuggerTransport;
            DebugAdapter       = new MeadowSolidityDebugAdapter(useContractsSubDir);
            DebugAdapter.OnDebuggerDisconnect += DebugAdapter_OnDebuggerDisconnect;
            DebugAdapter.OnDebuggerDisconnect += TeardownRpcDebuggingHook;
        }
        // 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;

            pRequest.GetPortName(out global::System.String name);

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

            var uri = new Uri(name, UriKind.Absolute);
            IDebuggerTransport 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);
            }

            PythonRemoteDebugPort 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);
        }
Esempio n. 3
0
        public static SolidityDebugger AttachSolidityDebugger(IDebuggerTransport debuggerTransport, CancellationTokenSource cancelToken = null, bool useContractsSubDir = true)
        {
            var debuggingInstance = new SolidityDebugger(debuggerTransport, useContractsSubDir);

            debuggingInstance.InitializeDebugConnection();
            IsSolidityDebuggerAttached = true;
            debuggingInstance.SetupRpcDebuggingHook();

            debuggingInstance.OnDebuggerDisconnect += () =>
            {
                // If the C# debugger is not attached, we don't care about running the rest of the tests
                // so exit program
                if (!Debugger.IsAttached)
                {
                    cancelToken?.Cancel();
                }
            };

            return(debuggingInstance);
        }
Esempio n. 4
0
        /// <summary>
        /// Connects to and performs the initial handshake with the remote debugging server, verifying protocol signature and version number,
        /// and returns the opened stream in a state ready to receive further ptvsd commands (e.g. attach).
        /// </summary>
        public static async Task <DebugConnection> ConnectAsync(Uri uri, bool warnAboutAuthenticationErrors, TextWriter debugLog, CancellationToken ct)
        {
            IDebuggerTransport transport = DebuggerTransportFactory.Get(uri);

            if (transport == null)
            {
                throw new ConnectionException(ConnErrorMessages.RemoteInvalidUri);
            }

            Stream stream = null;

            do
            {
                try
                {
                    stream = transport.Connect(uri, warnAboutAuthenticationErrors);
                }
                catch (AuthenticationException ex)
                {
                    if (!warnAboutAuthenticationErrors)
                    {
                        // This should never happen, but if it does, we don't want to keep trying.
                        throw new ConnectionException(ConnErrorMessages.RemoteSslError, ex);
                    }

                    string errText = Strings.RemoteProcessAuthenticationErrorWarning.FormatUI(ex.Message);
                    var    dlgRes  = MessageBox.Show(errText, Strings.ProductTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                    if (dlgRes == DialogResult.Yes)
                    {
                        warnAboutAuthenticationErrors = false;
                    }
                    else
                    {
                        throw new ConnectionException(ConnErrorMessages.RemoteSslError, ex);
                    }
                }
            } while (stream == null);

            DebugConnection debugConn = new DebugConnection(stream, debugLog);
            bool            connected = false;

            try
            {
                string serverDebuggerName            = string.Empty;
                int    serverDebuggerProtocolVersion = 0;
                using (var connectedEvent = new AutoResetEvent(false))
                {
                    EventHandler <LDP.RemoteConnectedEvent> eventReceived = (object sender, LDP.RemoteConnectedEvent ea) =>
                    {
                        serverDebuggerName            = ea.debuggerName;
                        serverDebuggerProtocolVersion = ea.debuggerProtocolVersion;
                        try
                        {
                            connectedEvent.Set();
                        }
                        catch (ObjectDisposedException)
                        {
                        }
                        debugConn.Authenticated();
                    };

                    // When the server accepts a connection, it sends an event and then waits for a request
                    debugConn.LegacyRemoteConnected += eventReceived;
                    try
                    {
                        debugConn.StartListening();
                        bool received = connectedEvent.WaitOne(ConnectTimeoutMs);
                        if (!received)
                        {
                            throw new ConnectionException(ConnErrorMessages.TimeOut);
                        }
                    }
                    finally
                    {
                        debugConn.LegacyRemoteConnected -= eventReceived;
                    }
                }

                if (serverDebuggerName != DebuggerSignature)
                {
                    throw new ConnectionException(ConnErrorMessages.RemoteUnsupportedServer);
                }

                // If we are talking the same protocol but different version, reply with signature + version before bailing out
                // so that ptvsd has a chance to gracefully close the socket on its side.
                var response = await debugConn.SendRequestAsync(new LDP.RemoteDebuggerAuthenticateRequest()
                {
                    clientSecret            = uri.UserInfo,
                    debuggerName            = DebuggerSignature,
                    debuggerProtocolVersion = DebuggerProtocolVersion,
                }, ct);

                if (serverDebuggerProtocolVersion != DebuggerProtocolVersion)
                {
                    throw new ConnectionException(ConnErrorMessages.RemoteUnsupportedServer);
                }

                if (!response.accepted)
                {
                    throw new ConnectionException(ConnErrorMessages.RemoteSecretMismatch);
                }

                connected = true;
                return(debugConn);
            }
            catch (IOException ex)
            {
                throw new ConnectionException(ConnErrorMessages.RemoteNetworkError, ex);
            }
            catch (SocketException ex)
            {
                throw new ConnectionException(ConnErrorMessages.RemoteNetworkError, ex);
            }
            finally
            {
                if (!connected)
                {
                    debugConn?.Dispose();
                }
            }
        }