/// <summary>
        /// Connects the subsystem using a new SSH channel session.
        /// </summary>
        /// <exception cref="InvalidOperationException">The session is already connected.</exception>
        /// <exception cref="ObjectDisposedException">The method was called after the session was disposed.</exception>
        public void Connect()
        {
            EnsureNotDisposed();

            if (IsOpen)
            {
                throw new InvalidOperationException("The session is already connected.");
            }

            // reset waithandles in case we're reconnecting
            _errorOccuredWaitHandle.Reset();
            _sessionDisconnectedWaitHandle.Reset();
            _sessionDisconnectedWaitHandle.Reset();
            _channelClosedWaitHandle.Reset();

            _session.ErrorOccured += Session_ErrorOccured;
            _session.Disconnected += Session_Disconnected;

            _channel = _session.CreateChannelSession();
            _channel.DataReceived += Channel_DataReceived;
            _channel.Exception    += Channel_Exception;
            _channel.Closed       += Channel_Closed;
            _channel.Open();
            _channel.SendSubsystemRequest(_subsystemName);

            OnChannelOpen();
        }
Exemple #2
0
        /// <summary>
        /// Initializes a new <see cref="ShellStream"/> instance.
        /// </summary>
        /// <param name="session">The SSH session.</param>
        /// <param name="terminalName">The <c>TERM</c> environment variable.</param>
        /// <param name="columns">The terminal width in columns.</param>
        /// <param name="rows">The terminal width in rows.</param>
        /// <param name="width">The terminal height in pixels.</param>
        /// <param name="height">The terminal height in pixels.</param>
        /// <param name="terminalModeValues">The terminal mode values.</param>
        /// <param name="bufferSize">The size of the buffer.</param>
        /// <exception cref="SshException">The channel could not be opened.</exception>
        /// <exception cref="SshException">The pseudo-terminal request was not accepted by the server.</exception>
        /// <exception cref="SshException">The request to start a shell was not accepted by the server.</exception>
        internal ShellStream(ISession session, string terminalName, uint columns, uint rows, uint width, uint height, IDictionary <TerminalModes, uint> terminalModeValues, int bufferSize)
        {
            _encoding   = session.ConnectionInfo.Encoding;
            _session    = session;
            _bufferSize = bufferSize;
            _incoming   = new Queue <byte>();
            _outgoing   = new Queue <byte>();

            _channel = _session.CreateChannelSession();
            _channel.DataReceived += Channel_DataReceived;
            _channel.Closed       += Channel_Closed;
            _session.Disconnected += Session_Disconnected;
            _session.ErrorOccured += Session_ErrorOccured;

            try
            {
                _channel.Open();
                if (!_channel.SendPseudoTerminalRequest(terminalName, columns, rows, width, height, terminalModeValues))
                {
                    throw new SshException("The pseudo-terminal request was not accepted by the server. Consult the server log for more information.");
                }
                if (!_channel.SendShellRequest())
                {
                    throw new SshException("The request to start a shell was not accepted by the server. Consult the server log for more information.");
                }
            }
            catch
            {
                UnsubscribeFromSessionEvents(session);
                _channel.Dispose();
                throw;
            }
        }
Exemple #3
0
        /// <summary>
        /// Begins an asynchronous command execution.
        /// </summary>
        /// <param name="callback">An optional asynchronous callback, to be called when the command execution is complete.</param>
        /// <param name="state">A user-provided object that distinguishes this particular asynchronous read request from other requests.</param>
        /// <returns>
        /// An <see cref="IAsyncResult" /> that represents the asynchronous command execution, which could still be pending.
        /// </returns>
        /// <exception cref="InvalidOperationException">Asynchronous operation is already in progress.</exception>
        /// <exception cref="SshException">Invalid operation.</exception>
        /// <exception cref="ArgumentException">CommandText property is empty.</exception>
        /// <exception cref="SshConnectionException">Client is not connected.</exception>
        /// <exception cref="SshOperationTimeoutException">Operation has timed out.</exception>
        /// <exception cref="InvalidOperationException">Asynchronous operation is already in progress.</exception>
        /// <exception cref="ArgumentException">CommandText property is empty.</exception>
        public IAsyncResult BeginExecute(AsyncCallback callback, object state)
        {
            //  Prevent from executing BeginExecute before calling EndExecute
            if (_asyncResult != null && !_asyncResult.EndCalled)
            {
                throw new InvalidOperationException("Asynchronous operation is already in progress.");
            }

            //  Create new AsyncResult object
            _asyncResult = new CommandAsyncResult
            {
                AsyncWaitHandle = new ManualResetEvent(false),
                IsCompleted     = false,
                AsyncState      = state,
            };

            //  When command re-executed again, create a new channel
            if (_channel != null)
            {
                throw new SshException("Invalid operation.");
            }

            if (string.IsNullOrEmpty(CommandText))
            {
                throw new ArgumentException("CommandText property is empty.");
            }

            var outputStream = OutputStream;

            if (outputStream != null)
            {
                outputStream.Dispose();
                OutputStream = null;
            }

            var extendedOutputStream = ExtendedOutputStream;

            if (extendedOutputStream != null)
            {
                extendedOutputStream.Dispose();
                ExtendedOutputStream = null;
            }

            //  Initialize output streams
            OutputStream         = new PipeStream();
            ExtendedOutputStream = new PipeStream();

            _result   = null;
            _error    = null;
            _callback = callback;

            _channel = CreateChannel();
            _channel.Open();
            _channel.SendExecRequest(CommandText);

            return(_asyncResult);
        }
Exemple #4
0
        internal ShellStream(ISession session, string terminalName, uint columns, uint rows, uint width, uint height, IDictionary <TerminalModes, uint> terminalModeValues)
        {
            _encoding = session.ConnectionInfo.Encoding;
            _session  = session;
            _incoming = new Queue <byte>();
            _outgoing = new Queue <byte>();

            _channel = _session.CreateChannelSession();
            _channel.DataReceived += Channel_DataReceived;
            _channel.Closed       += Channel_Closed;
            _session.Disconnected += Session_Disconnected;
            _session.ErrorOccured += Session_ErrorOccured;

            _channel.Open();
            _channel.SendPseudoTerminalRequest(terminalName, columns, rows, width, height, terminalModeValues);
            _channel.SendShellRequest();
        }
Exemple #5
0
        internal ShellStream(ISession session, string terminalName, uint columns, uint rows, uint width, uint height, IDictionary<TerminalModes, uint> terminalModeValues)
        {
            _encoding = session.ConnectionInfo.Encoding;
            _session = session;
            _incoming = new Queue<byte>();
            _outgoing = new Queue<byte>();

            _channel = _session.CreateChannelSession();
            _channel.DataReceived += Channel_DataReceived;
            _channel.Closed += Channel_Closed;
            _session.Disconnected += Session_Disconnected;
            _session.ErrorOccured += Session_ErrorOccured;

            _channel.Open();
            _channel.SendPseudoTerminalRequest(terminalName, columns, rows, width, height, terminalModeValues);
            _channel.SendShellRequest();
        }
        /// <summary>
        /// Connects the subsystem using a new SSH channel session.
        /// </summary>
        /// <exception cref="InvalidOperationException">The session is already connected.</exception>
        /// <exception cref="ObjectDisposedException">The method was called after the session was disposed.</exception>
        /// <exception cref="SshException">The channel session could not be opened, or the subsystem could not be executed.</exception>
        public void Connect()
        {
            EnsureNotDisposed();

            if (IsOpen)
            {
                throw new InvalidOperationException("The session is already connected.");
            }

            // reset waithandles in case we're reconnecting
            _errorOccuredWaitHandle.Reset();
            _sessionDisconnectedWaitHandle.Reset();
            _sessionDisconnectedWaitHandle.Reset();
            _channelClosedWaitHandle.Reset();

            _session.ErrorOccured += Session_ErrorOccured;
            _session.Disconnected += Session_Disconnected;

            _channel = _session.CreateChannelSession();
            _channel.DataReceived += Channel_DataReceived;
            _channel.Exception    += Channel_Exception;
            _channel.Closed       += Channel_Closed;
            _channel.Open();

            if (!_channel.SendSubsystemRequest(_subsystemName))
            {
                // close channel session
                Disconnect();
                // signal subsystem failure
                throw new SshException(string.Format(CultureInfo.InvariantCulture,
                                                     "Subsystem '{0}' could not be executed.",
                                                     _subsystemName));
            }

            OnChannelOpen();
        }
Exemple #7
0
        /// <summary>
        /// Starts this shell.
        /// </summary>
        /// <exception cref="SshException">Shell is started.</exception>
        public void Start()
        {
            if (IsStarted)
            {
                throw new SshException("Shell is started.");
            }

            if (Starting != null)
            {
                Starting(this, new EventArgs());
            }

            _channel = _session.CreateChannelSession();
            _channel.DataReceived         += Channel_DataReceived;
            _channel.ExtendedDataReceived += Channel_ExtendedDataReceived;
            _channel.Closed       += Channel_Closed;
            _session.Disconnected += Session_Disconnected;
            _session.ErrorOccured += Session_ErrorOccured;

            _channel.Open();
            _channel.SendPseudoTerminalRequest(_terminalName, _columns, _rows, _width, _height, _terminalModes);
            _channel.SendShellRequest();

            _channelClosedWaitHandle = new AutoResetEvent(false);

            //  Start input stream listener
            _dataReaderTaskCompleted = new ManualResetEvent(false);
            ThreadAbstraction.ExecuteThread(() =>
            {
                try
                {
                    var buffer = new byte[_bufferSize];

                    while (_channel.IsOpen)
                    {
#if FEATURE_STREAM_TAP
                        var readTask       = _input.ReadAsync(buffer, 0, buffer.Length);
                        var readWaitHandle = ((IAsyncResult)readTask).AsyncWaitHandle;

                        if (WaitHandle.WaitAny(new[] { readWaitHandle, _channelClosedWaitHandle }) == 0)
                        {
                            var read = readTask.Result;
                            _channel.SendData(buffer, 0, read);
                            continue;
                        }
#elif FEATURE_STREAM_APM
                        var asyncResult = _input.BeginRead(buffer, 0, buffer.Length, result =>
                        {
                            //  If input stream is closed and disposed already don't finish reading the stream
                            if (_input == null)
                            {
                                return;
                            }

                            var read = _input.EndRead(result);
                            _channel.SendData(buffer, 0, read);
                        }, null);

                        WaitHandle.WaitAny(new[] { asyncResult.AsyncWaitHandle, _channelClosedWaitHandle });

                        if (asyncResult.IsCompleted)
                        {
                            continue;
                        }
#else
                        #error Async receive is not implemented.
#endif
                        break;
                    }
                }
                catch (Exception exp)
                {
                    RaiseError(new ExceptionEventArgs(exp));
                }
                finally
                {
                    _dataReaderTaskCompleted.Set();
                }
            });

            IsStarted = true;

            if (Started != null)
            {
                Started(this, new EventArgs());
            }
        }
        /// <summary>
        /// Connects the subsystem using a new SSH channel session.
        /// </summary>
        /// <exception cref="InvalidOperationException">The session is already connected.</exception>
        /// <exception cref="ObjectDisposedException">The method was called after the session was disposed.</exception>
        public void Connect()
        {
            EnsureNotDisposed();

            if (IsOpen)
                throw new InvalidOperationException("The session is already connected.");

            // reset waithandles in case we're reconnecting
            _errorOccuredWaitHandle.Reset();
            _sessionDisconnectedWaitHandle.Reset();
            _sessionDisconnectedWaitHandle.Reset();
            _channelClosedWaitHandle.Reset();

            _session.ErrorOccured += Session_ErrorOccured;
            _session.Disconnected += Session_Disconnected;

            _channel = _session.CreateChannelSession();
            _channel.DataReceived += Channel_DataReceived;
            _channel.Exception += Channel_Exception;
            _channel.Closed += Channel_Closed;
            _channel.Open();
            _channel.SendSubsystemRequest(_subsystemName);

            OnChannelOpen();
        }
Exemple #9
0
        /// <summary>
        /// Starts this shell.
        /// </summary>
        /// <exception cref="SshException">Shell is started.</exception>
        public void Start()
        {
            if (IsStarted)
            {
                throw new SshException("Shell is started.");
            }

            if (Starting != null)
            {
                Starting(this, new EventArgs());
            }

            _channel = _session.CreateChannelSession();
            _channel.DataReceived += Channel_DataReceived;
            _channel.ExtendedDataReceived += Channel_ExtendedDataReceived;
            _channel.Closed += Channel_Closed;
            _session.Disconnected += Session_Disconnected;
            _session.ErrorOccured += Session_ErrorOccured;

            _channel.Open();
            _channel.SendPseudoTerminalRequest(_terminalName, _columns, _rows, _width, _height, _terminalModes);
            _channel.SendShellRequest();

            _channelClosedWaitHandle = new AutoResetEvent(false);

            //  Start input stream listener
            _dataReaderTaskCompleted = new ManualResetEvent(false);
            ThreadAbstraction.ExecuteThread(() =>
            {
                try
                {
                    var buffer = new byte[_bufferSize];

                    while (_channel.IsOpen)
                    {
#if FEATURE_STREAM_TAP
                        var readTask = _input.ReadAsync(buffer, 0, buffer.Length);
                        var readWaitHandle = ((IAsyncResult) readTask).AsyncWaitHandle;

                        if (WaitHandle.WaitAny(new[] {readWaitHandle, _channelClosedWaitHandle}) == 0)
                        {
                            var read = readTask.Result;
                            _channel.SendData(buffer, 0, read);
                            continue;
                        }
#elif FEATURE_STREAM_APM
                        var asyncResult = _input.BeginRead(buffer, 0, buffer.Length, result =>
                            {
                                //  If input stream is closed and disposed already don't finish reading the stream
                                if (_input == null)
                                    return;

                                var read = _input.EndRead(result);
                                _channel.SendData(buffer, 0, read);
                            }, null);

                        WaitHandle.WaitAny(new[] { asyncResult.AsyncWaitHandle, _channelClosedWaitHandle });

                        if (asyncResult.IsCompleted)
                            continue;
#else
                        #error Async receive is not implemented.
#endif
                        break;
                    }
                }
                catch (Exception exp)
                {
                    RaiseError(new ExceptionEventArgs(exp));
                }
                finally
                {
                    _dataReaderTaskCompleted.Set();
                }
            });

            IsStarted = true;

            if (Started != null)
            {
                Started(this, new EventArgs());
            }
        }
Exemple #10
0
        /// <summary>
        /// Starts this shell.
        /// </summary>
        /// <exception cref="SshException">Shell is started.</exception>
        public void Start()
        {
            if (IsStarted)
            {
                throw new SshException("Shell is started.");
            }

            if (Starting != null)
            {
                Starting(this, new EventArgs());
            }

            _channel = _session.CreateChannelSession();
            _channel.DataReceived += Channel_DataReceived;
            _channel.ExtendedDataReceived += Channel_ExtendedDataReceived;
            _channel.Closed += Channel_Closed;
            _session.Disconnected += Session_Disconnected;
            _session.ErrorOccured += Session_ErrorOccured;

            _channel.Open();
            _channel.SendPseudoTerminalRequest(_terminalName, _columns, _rows, _width, _height, _terminalModes);
            _channel.SendShellRequest();

            _channelClosedWaitHandle = new AutoResetEvent(false);

            //  Start input stream listener
            _dataReaderTaskCompleted = new ManualResetEvent(false);
            ExecuteThread(() =>
            {
                try
                {
                    var buffer = new byte[_bufferSize];

                    while (_channel.IsOpen)
                    {
                        var asyncResult = _input.BeginRead(buffer, 0, buffer.Length, delegate(IAsyncResult result)
                        {
                            //  If input stream is closed and disposed already dont finish reading the stream
                            if (_input == null)
                                return;

                            var read = _input.EndRead(result);
                            if (read > 0)
                            {
#if TUNING
                                _channel.SendData(buffer, 0, read);
#else
                                _channel.SendData(buffer.Take(read).ToArray());
#endif
                            }

                        }, null);

                        EventWaitHandle.WaitAny(new WaitHandle[] { asyncResult.AsyncWaitHandle, _channelClosedWaitHandle });

                        if (asyncResult.IsCompleted)
                            continue;
                        break;
                    }
                }
                catch (Exception exp)
                {
                    RaiseError(new ExceptionEventArgs(exp));
                }
                finally
                {
                    _dataReaderTaskCompleted.Set();
                }
            });

            IsStarted = true;

            if (Started != null)
            {
                Started(this, new EventArgs());
            }
        }
Exemple #11
0
        /// <summary>
        /// Starts this shell.
        /// </summary>
        /// <exception cref="SshException">Shell is started.</exception>
        public void Start()
        {
            if (IsStarted)
            {
                throw new SshException("Shell is started.");
            }

            if (Starting != null)
            {
                Starting(this, new EventArgs());
            }

            _channel = _session.CreateChannelSession();
            _channel.DataReceived         += Channel_DataReceived;
            _channel.ExtendedDataReceived += Channel_ExtendedDataReceived;
            _channel.Closed       += Channel_Closed;
            _session.Disconnected += Session_Disconnected;
            _session.ErrorOccured += Session_ErrorOccured;

            _channel.Open();
            _channel.SendPseudoTerminalRequest(_terminalName, _columns, _rows, _width, _height, _terminalModes);
            _channel.SendShellRequest();

            _channelClosedWaitHandle = new AutoResetEvent(false);

            //  Start input stream listener
            _dataReaderTaskCompleted = new ManualResetEvent(false);
            ExecuteThread(async() =>
            {
                try
                {
                    var buffer = new byte[_bufferSize];

                    while (_channel.IsOpen)
                    {
                        var read = await _input.ReadAsync(buffer, 0, buffer.Length);

                        if (read > 0)
                        {
#if true //old TUNING
                            _channel.SendData(buffer, 0, read);
#else
                            _channel.SendData(buffer.Take(read).ToArray());
#endif
                        }

                        if (_channelClosedWaitHandle.WaitOne(0))
                        {
                            break;
                        }
                    }
                }
                catch (Exception exp)
                {
                    RaiseError(new ExceptionEventArgs(exp));
                }
                finally
                {
                    _dataReaderTaskCompleted.Set();
                }
            });

            IsStarted = true;

            if (Started != null)
            {
                Started(this, new EventArgs());
            }
        }
Exemple #12
0
        /// <summary>
        /// Begins an asynchronous command execution.
        /// </summary>
        /// <param name="callback">An optional asynchronous callback, to be called when the command execution is complete.</param>
        /// <param name="state">A user-provided object that distinguishes this particular asynchronous read request from other requests.</param>
        /// <returns>
        /// An <see cref="IAsyncResult" /> that represents the asynchronous command execution, which could still be pending.
        /// </returns>
        /// <exception cref="InvalidOperationException">Asynchronous operation is already in progress.</exception>
        /// <exception cref="SshException">Invalid operation.</exception>
        /// <exception cref="ArgumentException">CommandText property is empty.</exception>
        /// <exception cref="SshConnectionException">Client is not connected.</exception>
        /// <exception cref="SshOperationTimeoutException">Operation has timed out.</exception>
        /// <exception cref="InvalidOperationException">Asynchronous operation is already in progress.</exception>
        /// <exception cref="ArgumentException">CommandText property is empty.</exception>
        public IAsyncResult BeginExecute(AsyncCallback callback, object state)
        {
            //  Prevent from executing BeginExecute before calling EndExecute
            if (_asyncResult != null && !_asyncResult.EndCalled)
            {
                throw new InvalidOperationException("Asynchronous operation is already in progress.");
            }

            //  Create new AsyncResult object
            _asyncResult = new CommandAsyncResult
                {
                    AsyncWaitHandle = new ManualResetEvent(false),
                    IsCompleted = false,
                    AsyncState = state,
                };

            //  When command re-executed again, create a new channel
            if (_channel != null)
            {
                throw new SshException("Invalid operation.");
            }

            if (string.IsNullOrEmpty(CommandText))
                throw new ArgumentException("CommandText property is empty.");

            var outputStream = OutputStream;
            if (outputStream != null)
            {
                outputStream.Dispose();
                OutputStream = null;
            }

            var extendedOutputStream = ExtendedOutputStream;
            if (extendedOutputStream != null)
            {
                extendedOutputStream.Dispose();
                ExtendedOutputStream = null;
            }

            //  Initialize output streams
            OutputStream = new PipeStream();
            ExtendedOutputStream = new PipeStream();

            _result = null;
            _error = null;
            _callback = callback;

            _channel = CreateChannel();
            _channel.Open();
            _channel.SendExecRequest(CommandText);

            return _asyncResult;
        }
Exemple #13
0
        /// <summary>
        /// Starts this shell.
        /// </summary>
        /// <exception cref="SshException">Shell is started.</exception>
        public void Start()
        {
            if (IsStarted)
            {
                throw new SshException("Shell is started.");
            }

            if (Starting != null)
            {
                Starting(this, new EventArgs());
            }

            _channel = _session.CreateChannelSession();
            _channel.DataReceived         += Channel_DataReceived;
            _channel.ExtendedDataReceived += Channel_ExtendedDataReceived;
            _channel.Closed       += Channel_Closed;
            _session.Disconnected += Session_Disconnected;
            _session.ErrorOccured += Session_ErrorOccured;

            _channel.Open();
            _channel.SendPseudoTerminalRequest(_terminalName, _columns, _rows, _width, _height, _terminalModes);
            _channel.SendShellRequest();

            _channelClosedWaitHandle = new AutoResetEvent(false);

            //  Start input stream listener
            _dataReaderTaskCompleted = new ManualResetEvent(false);
            ExecuteThread(() =>
            {
                try
                {
                    var buffer = new byte[_bufferSize];

                    while (_channel.IsOpen)
                    {
                        var asyncResult = _input.BeginRead(buffer, 0, buffer.Length, delegate(IAsyncResult result)
                        {
                            //  If input stream is closed and disposed already dont finish reading the stream
                            if (_input == null)
                            {
                                return;
                            }

                            var read = _input.EndRead(result);
                            if (read > 0)
                            {
#if TUNING
                                _channel.SendData(buffer, 0, read);
#else
                                _channel.SendData(buffer.Take(read).ToArray());
#endif
                            }
                        }, null);

                        EventWaitHandle.WaitAny(new WaitHandle[] { asyncResult.AsyncWaitHandle, _channelClosedWaitHandle });

                        if (asyncResult.IsCompleted)
                        {
                            continue;
                        }
                        break;
                    }
                }
                catch (Exception exp)
                {
                    RaiseError(new ExceptionEventArgs(exp));
                }
                finally
                {
                    _dataReaderTaskCompleted.Set();
                }
            });

            IsStarted = true;

            if (Started != null)
            {
                Started(this, new EventArgs());
            }
        }