Example #1
0
        private void Channel_Closed(object sender, ChannelEventArgs e)
        {
            var outputStream = OutputStream;

            if (outputStream != null)
            {
                outputStream.Flush();
            }

            var extendedOutputStream = ExtendedOutputStream;

            if (extendedOutputStream != null)
            {
                extendedOutputStream.Flush();
            }

            _asyncResult.IsCompleted = true;

            if (_callback != null)
            {
                //  Execute callback on different thread
                ThreadAbstraction.ExecuteThread(() => _callback(_asyncResult));
            }
            ((EventWaitHandle)_asyncResult.AsyncWaitHandle).Set();
        }
Example #2
0
        /// <summary>
        /// Waits for pending requests to finish, and channels to close.
        /// </summary>
        /// <param name="timeout">The maximum time to wait for the forwarded port to stop.</param>
        partial void InternalStop(TimeSpan timeout)
        {
            if (timeout == TimeSpan.Zero)
            {
                return;
            }

            var stopWatch = new Stopwatch();

            stopWatch.Start();

            // break out of loop when one of the following conditions are met:
            // * the forwarded port is restarted
            // * all pending requests have been processed and corresponding channel are closed
            // * the specified timeout has elapsed
            while (!IsStarted)
            {
                // break out of loop when all pending requests have been processed
                if (Interlocked.CompareExchange(ref _pendingRequests, 0, 0) == 0)
                {
                    break;
                }
                // break out of loop when specified timeout has elapsed
                if (stopWatch.Elapsed >= timeout && timeout != SshNet.Session.InfiniteTimeSpan)
                {
                    break;
                }
                // give channels time to process pending requests
                ThreadAbstraction.Sleep(50);
            }

            stopWatch.Stop();
        }
        partial void InternalStop(TimeSpan timeout)
        {
            if (timeout == TimeSpan.Zero)
            {
                return;
            }

            var stopWatch = new Stopwatch();

            stopWatch.Start();

            while (true)
            {
                // break out of loop when all pending requests have been processed
                if (Interlocked.CompareExchange(ref _pendingRequests, 0, 0) == 0)
                {
                    break;
                }
                // break out of loop when specified timeout has elapsed
                if (stopWatch.Elapsed >= timeout && timeout != SshNet.Session.InfiniteTimeSpan)
                {
                    break;
                }
                // give channels time to process pending requests
                ThreadAbstraction.Sleep(50);
            }

            stopWatch.Stop();
        }
Example #4
0
        private void Session_ChannelOpening(object sender, MessageEventArgs <ChannelOpenMessage> e)
        {
            var channelOpenMessage = e.Message;
            var info = channelOpenMessage.Info as ForwardedTcpipChannelInfo;

            if (info != null)
            {
                //  Ensure this is the corresponding request
                if (info.ConnectedAddress == BoundHost && info.ConnectedPort == BoundPort)
                {
                    if (!IsStarted)
                    {
                        Session.SendMessage(new ChannelOpenFailureMessage(channelOpenMessage.LocalChannelNumber, "", ChannelOpenFailureMessage.AdministrativelyProhibited));
                        return;
                    }

                    ThreadAbstraction.ExecuteThread(() =>
                    {
                        // capture the countdown event that we're adding a count to, as we need to make sure that we'll be signaling
                        // that same instance; the instance field for the countdown event is re-initialize when the port is restarted
                        // and that time there may still be pending requests
                        var pendingChannelCountdown = _pendingChannelCountdown;

                        pendingChannelCountdown.AddCount();

                        try
                        {
                            RaiseRequestReceived(info.OriginatorAddress, info.OriginatorPort);

                            using (
                                var channel =
                                    Session.CreateChannelForwardedTcpip(channelOpenMessage.LocalChannelNumber,
                                                                        channelOpenMessage.InitialWindowSize, channelOpenMessage.MaximumPacketSize))
                            {
                                channel.Exception += Channel_Exception;
                                channel.Bind(new IPEndPoint(HostAddress, (int)Port), this);
                                channel.Close();
                            }
                        }
                        catch (Exception exp)
                        {
                            RaiseExceptionEvent(exp);
                        }
                        finally
                        {
                            // take into account that CountdownEvent has since been disposed; when stopping the port we
                            // wait for a given time for the channels to close, but once that timeout period has elapsed
                            // the CountdownEvent will be disposed
                            try
                            {
                                pendingChannelCountdown.Signal();
                            }
                            catch (ObjectDisposedException)
                            {
                            }
                        }
                    });
                }
            }
        }
        public void ShouldExecuteActionOnSeparateThread()
        {
            DateTime?       executionTime  = null;
            int             executionCount = 0;
            EventWaitHandle waitHandle     = new ManualResetEvent(false);

            Action action = () =>
            {
                ThreadAbstraction.Sleep(500);
                executionCount++;
                executionTime = DateTime.Now;
                waitHandle.Set();
            };

            DateTime start = DateTime.Now;

            ThreadAbstraction.ExecuteThread(action);

            Assert.AreEqual(0, executionCount);
            Assert.IsNull(executionTime);

            Assert.IsTrue(waitHandle.WaitOne(2000));

            Assert.AreEqual(1, executionCount);
            Assert.IsNotNull(executionTime);

            var elapsedTime = executionTime.Value - start;

            Assert.IsTrue(elapsedTime > TimeSpan.Zero);
            Assert.IsTrue(elapsedTime > TimeSpan.FromMilliseconds(500));
            Assert.IsTrue(elapsedTime < TimeSpan.FromMilliseconds(1000));
        }
Example #6
0
        private void Channel_Closed(object sender, ChannelEventArgs e)
        {
            if (Stopping != null)
            {
                //  Handle event on different thread
                ThreadAbstraction.ExecuteThread(() => Stopping(this, new EventArgs()));
            }

            _channel.Dispose();
            _channelClosedWaitHandle.Set();

            _input.Dispose();
            _input = null;

            _dataReaderTaskCompleted.WaitOne(_session.ConnectionInfo.Timeout);
            _dataReaderTaskCompleted.Dispose();
            _dataReaderTaskCompleted = null;

            _channel.DataReceived         -= Channel_DataReceived;
            _channel.ExtendedDataReceived -= Channel_ExtendedDataReceived;
            _channel.Closed -= Channel_Closed;

            UnsubscribeFromSessionEvents(_session);

            if (Stopped != null)
            {
                //  Handle event on different thread
                ThreadAbstraction.ExecuteThread(() => Stopped(this, new EventArgs()));
            }

            _channel = null;
        }
        private void Session_MessageReceived(object sender, MessageEventArgs <Message> e)
        {
            if (e.Message is PasswordChangeRequiredMessage)
            {
                _session.UnRegisterMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");

                ThreadAbstraction.ExecuteThread(() =>
                {
                    try
                    {
                        var eventArgs = new AuthenticationPasswordChangeEventArgs(Username);

                        //  Raise an event to allow user to supply a new password
                        if (PasswordExpired != null)
                        {
                            PasswordExpired(this, eventArgs);
                        }

                        //  Send new authentication request with new password
                        _session.SendMessage(new RequestMessagePassword(ServiceName.Connection, Username, _password, eventArgs.NewPassword));
                    }
                    catch (Exception exp)
                    {
                        _exception = exp;
                        _authenticationCompleted.Set();
                    }
                });
            }
        }
Example #8
0
        private void Session_UserAuthenticationInformationRequestReceived(object sender, MessageEventArgs <InformationRequestMessage> e)
        {
            var informationRequestMessage = e.Message;

            var eventArgs = new AuthenticationPromptEventArgs(Username,
                                                              informationRequestMessage.Instruction,
                                                              informationRequestMessage.Language,
                                                              informationRequestMessage.Prompts);

            ThreadAbstraction.ExecuteThread(() =>
            {
                try
                {
                    if (AuthenticationPrompt != null)
                    {
                        AuthenticationPrompt(this, eventArgs);
                    }

                    var informationResponse = new InformationResponseMessage();

                    foreach (var response in from r in eventArgs.Prompts orderby r.Id ascending select r.Response)
                    {
                        informationResponse.Responses.Add(response);
                    }

                    //  Send information response message
                    _session.SendMessage(informationResponse);
                }
                catch (Exception exp)
                {
                    _exception = exp;
                    _authenticationCompleted.Set();
                }
            });
        }
        partial void InternalStart()
        {
            var addr = DnsAbstraction.GetHostAddresses(BoundHost)[0];
            var ep   = new IPEndPoint(addr, (int)BoundPort);

            _listener = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            // TODO: decide if we want to have blocking socket
#if FEATURE_SOCKET_SETSOCKETOPTION
            _listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
#endif // FEATURE_SOCKET_SETSOCKETOPTION
            _listener.Bind(ep);
            _listener.Listen(1);

            // update bound port (in case original was passed as zero)
            BoundPort = (uint)((IPEndPoint)_listener.LocalEndPoint).Port;

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

            _listenerTaskCompleted = new ManualResetEvent(false);

            ThreadAbstraction.ExecuteThread(() =>
            {
                try
                {
#if FEATURE_SOCKET_EAP
                    _stoppingListener = new ManualResetEvent(false);
                    StartAccept();
                    _stoppingListener.WaitOne();
#elif FEATURE_SOCKET_APM
                    while (true)
                    {
                        // accept new inbound connection
                        var asyncResult = _listener.BeginAccept(AcceptCallback, _listener);
                        // wait for the connection to be established
                        asyncResult.AsyncWaitHandle.WaitOne();
                    }
#elif FEATURE_SOCKET_TAP
#error Accepting new socket connections is not implemented.
#else
#error Accepting new socket connections is not implemented.
#endif
                }
                catch (ObjectDisposedException)
                {
                    // BeginAccept will throw an ObjectDisposedException when the
                    // socket is closed
                }
                catch (Exception ex)
                {
                    RaiseExceptionEvent(ex);
                }
                finally
                {
                    // mark listener stopped
                    _listenerTaskCompleted.Set();
                }
            });
        }
Example #10
0
        /// <summary>
        /// Called when channel is closed by the server.
        /// </summary>
        protected override void OnClose()
        {
            base.OnClose();

            //  This timeout needed since when channel is closed it does not immediately becomes available
            //  but it takes time for the server to clean up resource and allow new channels to be created.
            ThreadAbstraction.Sleep(100);
        }
        private void StartReadAhead()
        {
            ThreadAbstraction.ExecuteThread(() =>
            {
                while (!_endOfFileReceived && _exception == null)
                {
                    // check if we should continue with the read-ahead loop
                    // note that the EOF and exception check are not included
                    // in this check as they do not require Read() to be
                    // unblocked (or have already done this)
                    if (!ContinueReadAhead())
                    {
                        // unblock the Read()
                        lock (_readLock)
                        {
                            Monitor.PulseAll(_readLock);
                        }
                        // break the read-ahead loop
                        break;
                    }

                    // attempt to obtain the semaphore; this may time out when all semaphores are
                    // in use due to pending read-aheads (which in turn can happen when the server
                    // is slow to respond or when the session is broken)
                    if (!_semaphore.Wait(ReadAheadWaitTimeoutInMilliseconds))
                    {
                        // re-evaluate whether an exception occurred, and - if not - wait again
                        continue;
                    }

                    // don't bother reading any more chunks if we received EOF, or an exception has occurred
                    // while processing a chunk
                    if (_endOfFileReceived || _exception != null)
                    {
                        break;
                    }

                    // start reading next chunk
                    try
                    {
                        _sftpSession.BeginRead(_handle, _readAheadOffset, _chunkSize, ReadCompleted,
                                               new BufferedRead(_readAheadChunkIndex, _readAheadOffset));
                    }
                    catch (Exception ex)
                    {
                        HandleFailure(ex);
                        break;
                    }

                    // advance read-ahead offset
                    _readAheadOffset += _chunkSize;

                    _readAheadChunkIndex++;
                }

                _readAheadCompleted.Set();
            });
        }
Example #12
0
        private static int ReadByte(Stream stream)
        {
            var b = stream.ReadByte();

            while (b < 0)
            {
                ThreadAbstraction.Sleep(100);
                b = stream.ReadByte();
            }

            return(b);
        }
Example #13
0
        protected override void SetupMocks()
        {
            _seq = new MockSequence();

            SftpSessionMock.InSequence(_seq)
            .Setup(p => p.CreateWaitHandleArray(It.IsNotNull <WaitHandle>(), It.IsNotNull <WaitHandle>()))
            .Returns <WaitHandle, WaitHandle>((disposingWaitHandle, semaphoreAvailableWaitHandle) =>
            {
                _waitHandleArray[0] = disposingWaitHandle;
                _waitHandleArray[1] = semaphoreAvailableWaitHandle;
                return(_waitHandleArray);
            });
            SftpSessionMock.InSequence(_seq).Setup(p => p.OperationTimeout).Returns(_operationTimeout);
            SftpSessionMock.InSequence(_seq)
            .Setup(p => p.WaitAny(_waitHandleArray, _operationTimeout))
            .Returns(() => WaitAny(_waitHandleArray, _operationTimeout));
            SftpSessionMock.InSequence(_seq)
            .Setup(p => p.BeginRead(_handle, 0, ChunkLength, It.IsNotNull <AsyncCallback>(), It.IsAny <BufferedRead>()))
            .Callback <byte[], ulong, uint, AsyncCallback, object>((handle, offset, length, callback, state) =>
            {
                var asyncResult = new SftpReadAsyncResult(callback, state);
                asyncResult.SetAsCompleted(_chunk1, false);
            })
            .Returns((SftpReadAsyncResult)null);
            SftpSessionMock.InSequence(_seq).Setup(p => p.OperationTimeout).Returns(_operationTimeout);
            SftpSessionMock.InSequence(_seq)
            .Setup(p => p.WaitAny(_waitHandleArray, _operationTimeout))
            .Returns(() => WaitAny(_waitHandleArray, _operationTimeout));
            SftpSessionMock.InSequence(_seq)
            .Setup(p => p.BeginRead(_handle, ChunkLength, ChunkLength, It.IsNotNull <AsyncCallback>(), It.IsAny <BufferedRead>()))
            .Callback <byte[], ulong, uint, AsyncCallback, object>((handle, offset, length, callback, state) =>
            {
                ThreadAbstraction.ExecuteThread(() =>
                {
                    // signal that we're in the read-ahead for chunk2
                    _readAheadChunk2.Set();
                    // wait for client to start reading this chunk
                    _readChunk2.WaitOne(TimeSpan.FromSeconds(5));
                    // sleep a short time to make sure the client is in the blocking wait
                    Thread.Sleep(500);
                    // complete async read of chunk2 with exception
                    var asyncResult = new SftpReadAsyncResult(callback, state);
                    asyncResult.SetAsCompleted(_exception, false);
                });
            })
            .Returns((SftpReadAsyncResult)null);
            SftpSessionMock.InSequence(_seq).Setup(p => p.OperationTimeout).Returns(_operationTimeout);
            SftpSessionMock.InSequence(_seq)
            .Setup(p => p.WaitAny(_waitHandleArray, _operationTimeout))
            .Returns(() => WaitAny(_waitHandleArray, _operationTimeout));
        }
        public void ShouldThrowArgumentNullExceptionWhenActionIsNull()
        {
            const Action action = null;

            try
            {
                ThreadAbstraction.ExecuteThread(action);
                Assert.Fail();
            }
            catch (ArgumentNullException ex)
            {
                Assert.IsNull(ex.InnerException);
                Assert.AreEqual("action", ex.ParamName);
            }
        }
        /// <summary>
        /// Stops remote port forwarding.
        /// </summary>
        /// <param name="timeout">The maximum amount of time to wait for pending requests to finish processing.</param>
        protected override void StopPort(TimeSpan timeout)
        {
            // if the port not started, then there's nothing to stop
            if (!IsStarted)
            {
                return;
            }

            // mark forwarded port stopped, this also causes open of new channels to be rejected
            _isStarted = false;

            base.StopPort(timeout);

            // send global request to cancel direct tcpip
            Session.SendMessage(new GlobalRequestMessage(GlobalRequestName.CancelTcpIpForward, true, BoundHost, BoundPort));
            // wait for response on global request to cancel direct tcpip or completion of message
            // listener loop (in which case response on global request can never be received)
            WaitHandle.WaitAny(new[] { _globalRequestResponse, Session.MessageListenerCompleted }, timeout);

            // unsubscribe from session events as either the tcpip forward is cancelled at the
            // server, or our session message loop has completed
            Session.RequestSuccessReceived -= Session_RequestSuccess;
            Session.RequestFailureReceived -= Session_RequestFailure;
            Session.ChannelOpenReceived    -= Session_ChannelOpening;

            var startWaiting = DateTime.Now;

            while (true)
            {
                // break out of loop when all pending requests have been processed
                if (Interlocked.CompareExchange(ref _pendingRequests, 0, 0) == 0)
                {
                    break;
                }
                // determine time elapsed since waiting for pending requests to finish
                var elapsed = DateTime.Now - startWaiting;
                // break out of loop when specified timeout has elapsed
                if (elapsed >= timeout && timeout != SshNet.Session.InfiniteTimeSpan)
                {
                    break;
                }
                // give channels time to process pending requests
                ThreadAbstraction.Sleep(50);
            }
        }
        private void Session_ChannelOpening(object sender, MessageEventArgs <ChannelOpenMessage> e)
        {
            var channelOpenMessage = e.Message;
            var info = channelOpenMessage.Info as ForwardedTcpipChannelInfo;

            if (info != null)
            {
                //  Ensure this is the corresponding request
                if (info.ConnectedAddress == BoundHost && info.ConnectedPort == BoundPort)
                {
                    if (!_isStarted)
                    {
                        Session.SendMessage(new ChannelOpenFailureMessage(channelOpenMessage.LocalChannelNumber, "", ChannelOpenFailureMessage.AdministrativelyProhibited));
                        return;
                    }

                    ThreadAbstraction.ExecuteThread(() =>
                    {
                        Interlocked.Increment(ref _pendingRequests);

                        try
                        {
                            RaiseRequestReceived(info.OriginatorAddress, info.OriginatorPort);

                            using (var channel = Session.CreateChannelForwardedTcpip(channelOpenMessage.LocalChannelNumber, channelOpenMessage.InitialWindowSize, channelOpenMessage.MaximumPacketSize))
                            {
                                channel.Exception += Channel_Exception;
                                channel.Bind(new IPEndPoint(HostAddress, (int)Port), this);
                                channel.Close();
                            }
                        }
                        catch (Exception exp)
                        {
                            RaiseExceptionEvent(exp);
                        }
                        finally
                        {
                            Interlocked.Decrement(ref _pendingRequests);
                        }
                    });
                }
            }
        }
Example #17
0
        protected override void Act()
        {
            ThreadAbstraction.ExecuteThread(() =>
            {
                Thread.Sleep(500);
                _reader.Dispose();
                _disposeCompleted.Set();
            });

            try
            {
                _reader.Read();
                Assert.Fail();
            }
            catch (ObjectDisposedException ex)
            {
                _actualException = ex;
            }

            // Dispose may unblock Read() before the dispose has fully completed, so
            // let's wait until it has completed
            _disposeCompleted.WaitOne(500);
        }
Example #18
0
        protected override void SetupMocks()
        {
            _seq = new MockSequence();

            SftpSessionMock.InSequence(_seq)
            .Setup(p => p.CreateWaitHandleArray(It.IsNotNull <WaitHandle>(), It.IsNotNull <WaitHandle>()))
            .Returns <WaitHandle, WaitHandle>((disposingWaitHandle, semaphoreAvailableWaitHandle) =>
            {
                _waitHandleArray[0] = disposingWaitHandle;
                _waitHandleArray[1] = semaphoreAvailableWaitHandle;
                return(_waitHandleArray);
            });
            SftpSessionMock.InSequence(_seq).Setup(p => p.OperationTimeout).Returns(_operationTimeout);
            SftpSessionMock.InSequence(_seq)
            .Setup(p => p.WaitAny(_waitHandleArray, _operationTimeout))
            .Returns(() => WaitAny(_waitHandleArray, _operationTimeout));
            SftpSessionMock.InSequence(_seq)
            .Setup(p => p.BeginRead(_handle, 0, ChunkLength, It.IsNotNull <AsyncCallback>(), It.IsAny <BufferedRead>()))
            .Callback <byte[], ulong, uint, AsyncCallback, object>((handle, offset, length, callback, state) =>
            {
                var asyncResult = new SftpReadAsyncResult(callback, state);
                asyncResult.SetAsCompleted(_chunk1, false);
            })
            .Returns((SftpReadAsyncResult)null);
            SftpSessionMock.InSequence(_seq).Setup(p => p.OperationTimeout).Returns(_operationTimeout);
            SftpSessionMock.InSequence(_seq)
            .Setup(p => p.WaitAny(_waitHandleArray, _operationTimeout))
            .Returns(() => WaitAny(_waitHandleArray, _operationTimeout));
            SftpSessionMock.InSequence(_seq)
            .Setup(p => p.BeginRead(_handle, ChunkLength, ChunkLength, It.IsNotNull <AsyncCallback>(), It.IsAny <BufferedRead>()))
            .Callback <byte[], ulong, uint, AsyncCallback, object>((handle, offset, length, callback, state) =>
            {
                ThreadAbstraction.ExecuteThread(() =>
                {
                    // wait until the read-ahead for chunk3 has completed; this should allow
                    // the read-ahead of chunk4 to start
                    _readAheadChunk3Completed.WaitOne(TimeSpan.FromSeconds(3));
                    // wait until the semaphore wait to start with chunk4 has started
                    _waitingForSemaphoreAfterCompletingChunk3.WaitOne(TimeSpan.FromSeconds(7));
                    // complete async read of chunk2 with exception
                    var asyncResult = new SftpReadAsyncResult(callback, state);
                    asyncResult.SetAsCompleted(_exception, false);
                    // signal that read-ahead of chunk 2 has completed
                    _readAheadChunk2Completed.Set();
                });
            })
            .Returns((SftpReadAsyncResult)null);
            SftpSessionMock.InSequence(_seq).Setup(p => p.OperationTimeout).Returns(_operationTimeout);
            SftpSessionMock.InSequence(_seq)
            .Setup(p => p.WaitAny(_waitHandleArray, _operationTimeout))
            .Returns(() => WaitAny(_waitHandleArray, _operationTimeout));
            SftpSessionMock.InSequence(_seq)
            .Setup(p => p.BeginRead(_handle, 2 * ChunkLength, ChunkLength, It.IsNotNull <AsyncCallback>(), It.IsAny <BufferedRead>()))
            .Callback <byte[], ulong, uint, AsyncCallback, object>((handle, offset, length, callback, state) =>
            {
                var asyncResult = new SftpReadAsyncResult(callback, state);
                asyncResult.SetAsCompleted(_chunk3, false);
                // signal that we've completed the read-ahead for chunk3
                _readAheadChunk3Completed.Set();
            })
            .Returns((SftpReadAsyncResult)null);
            SftpSessionMock.InSequence(_seq).Setup(p => p.OperationTimeout).Returns(_operationTimeout);
            SftpSessionMock.InSequence(_seq)
            .Setup(p => p.WaitAny(_waitHandleArray, _operationTimeout))
            .Callback(() => _waitingForSemaphoreAfterCompletingChunk3.Set())
            .Returns(() => WaitAny(_waitHandleArray, _operationTimeout));
        }
Example #19
0
        partial void InternalStart()
        {
            var ip = IPAddress.Any;

            if (!string.IsNullOrEmpty(BoundHost))
            {
                ip = DnsAbstraction.GetHostAddresses(BoundHost)[0];
            }

            var ep = new IPEndPoint(ip, (int)BoundPort);

            _listener = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            // TODO: decide if we want to have blocking socket
#if FEATURE_SOCKET_SETSOCKETOPTION
            _listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
            _listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
#endif //FEATURE_SOCKET_SETSOCKETOPTION
            _listener.Bind(ep);
            _listener.Listen(5);

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

            _listenerCompleted = new ManualResetEvent(false);

            ThreadAbstraction.ExecuteThread(() =>
            {
                try
                {
#if FEATURE_SOCKET_EAP
                    _stoppingListener = new ManualResetEvent(false);

                    StartAccept();

                    _stoppingListener.WaitOne();
#elif FEATURE_SOCKET_APM
                    while (true)
                    {
                        // accept new inbound connection
                        var asyncResult = _listener.BeginAccept(AcceptCallback, _listener);
                        // wait for the connection to be established
                        asyncResult.AsyncWaitHandle.WaitOne();
                    }
                }
                catch (ObjectDisposedException)
                {
                    // BeginAccept will throw an ObjectDisposedException when the
                    // socket is closed
#elif FEATURE_SOCKET_TAP
#error Accepting new socket connections is not implemented.
#else
#error Accepting new socket connections is not implemented.
#endif
                }
                catch (Exception ex)
                {
                    RaiseExceptionEvent(ex);
                }
                finally
                {
                    if (Session != null)
                    {
                        Session.ErrorOccured -= Session_ErrorOccured;
                        Session.Disconnected -= Session_Disconnected;
                    }

                    // mark listener stopped
                    _listenerCompleted.Set();
                }
            });
        }
Example #20
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());
            }
        }
Example #21
0
        /// <summary>
        /// Begins the expect.
        /// </summary>
        /// <param name="timeout">The timeout.</param>
        /// <param name="callback">The callback.</param>
        /// <param name="state">The state.</param>
        /// <param name="expectActions">The expect actions.</param>
        /// <returns>
        /// An <see cref="IAsyncResult" /> that references the asynchronous operation.
        /// </returns>
        public IAsyncResult BeginExpect(TimeSpan timeout, AsyncCallback callback, object state, params ExpectAction[] expectActions)
        {
            var text = string.Empty;

            //  Create new AsyncResult object
            var asyncResult = new ExpectAsyncResult(callback, state);

            //  Execute callback on different thread
            ThreadAbstraction.ExecuteThread(() =>
            {
                string expectActionResult = null;
                try
                {
                    do
                    {
                        lock (_incoming)
                        {
                            if (_incoming.Count > 0)
                            {
                                text = _encoding.GetString(_incoming.ToArray(), 0, _incoming.Count);
                            }

                            if (text.Length > 0)
                            {
                                foreach (var expectAction in expectActions)
                                {
                                    var match = expectAction.Expect.Match(text);

                                    if (match.Success)
                                    {
                                        var result = text.Substring(0, match.Index + match.Length);

                                        for (var i = 0; i < match.Index + match.Length && _incoming.Count > 0; i++)
                                        {
                                            //  Remove processed items from the queue
                                            _incoming.Dequeue();
                                        }

                                        expectAction.Action(result);

                                        if (callback != null)
                                        {
                                            callback(asyncResult);
                                        }
                                        expectActionResult = result;
                                    }
                                }
                            }
                        }

                        if (expectActionResult != null)
                        {
                            break;
                        }

                        if (timeout.Ticks > 0)
                        {
                            if (!_dataReceived.WaitOne(timeout))
                            {
                                if (callback != null)
                                {
                                    callback(asyncResult);
                                }
                                break;
                            }
                        }
                        else
                        {
                            _dataReceived.WaitOne();
                        }
                    } while (true);

                    asyncResult.SetAsCompleted(expectActionResult, true);
                }
                catch (Exception exp)
                {
                    asyncResult.SetAsCompleted(exp, true);
                }
            });

            return(asyncResult);
        }
Example #22
0
        private void StartReadAhead()
        {
            ThreadAbstraction.ExecuteThread(() =>
            {
                while (!_endOfFileReceived && _exception == null)
                {
                    // check if we should continue with the read-ahead loop
                    // note that the EOF and exception check are not included
                    // in this check as they do not require Read() to be
                    // unblocked (or have already done this)
                    if (!ContinueReadAhead())
                    {
                        // unblock the Read()
                        lock (_readLock)
                        {
                            Monitor.PulseAll(_readLock);
                        }
                        // break the read-ahead loop
                        break;
                    }

                    // attempt to obtain the semaphore; this may time out when all semaphores are
                    // in use due to pending read-aheads (which in turn can happen when the server
                    // is slow to respond or when the session is broken)
                    if (!_semaphore.Wait(ReadAheadWaitTimeoutInMilliseconds))
                    {
                        // re-evaluate whether an exception occurred, and - if not - wait again
                        continue;
                    }

                    // don't bother reading any more chunks if we received EOF, an exception has occurred
                    // or the current instance is disposed
                    if (_endOfFileReceived || _exception != null)
                    {
                        break;
                    }

                    // start reading next chunk
                    var bufferedRead = new BufferedRead(_readAheadChunkIndex, _readAheadOffset);

                    try
                    {
                        // even if we know the size of the file and have read up to EOF, we still want
                        // to keep reading (ahead) until we receive zero bytes from the remote host as
                        // we do not want to rely purely on the reported file size
                        //
                        // if the offset of the read-ahead chunk is greater than that file size, then
                        // we can expect to be reading the last (zero-byte) chunk and switch to synchronous
                        // mode to avoid having multiple read-aheads that read beyond EOF
                        if (_fileSize != null && (long)_readAheadOffset > _fileSize.Value)
                        {
                            var asyncResult = _sftpSession.BeginRead(_handle, _readAheadOffset, _chunkSize, null,
                                                                     bufferedRead);
                            var data = _sftpSession.EndRead(asyncResult);
                            ReadCompletedCore(bufferedRead, data);
                        }
                        else
                        {
                            _sftpSession.BeginRead(_handle, _readAheadOffset, _chunkSize, ReadCompleted, bufferedRead);
                        }
                    }
                    catch (Exception ex)
                    {
                        HandleFailure(ex);
                        break;
                    }

                    // advance read-ahead offset
                    _readAheadOffset += _chunkSize;
                    // increment index of read-ahead chunk
                    _readAheadChunkIndex++;
                }

                _readAheadCompleted.Set();
            });
        }
        partial void InternalStart()
        {
            var ip = IPAddress.Any;

            if (!string.IsNullOrEmpty(BoundHost))
            {
                ip = DnsAbstraction.GetHostAddresses(BoundHost)[0];
            }

            var ep = new IPEndPoint(ip, (int)BoundPort);

            _listener = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            // TODO: decide if we want to have blocking socket
#if FEATURE_SOCKET_SETSOCKETOPTION
            _listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
            _listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
#endif //FEATURE_SOCKET_SETSOCKETOPTION
            _listener.Bind(ep);
            _listener.Listen(5);

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

            _listenerCompleted = new ManualResetEvent(false);

            ThreadAbstraction.ExecuteThread(() =>
            {
                try
                {
#if FEATURE_SOCKET_EAP
                    StartAccept();
#elif FEATURE_SOCKET_APM
                    _listener.BeginAccept(AcceptCallback, _listener);
#elif FEATURE_SOCKET_TAP
#error Accepting new socket connections is not implemented.
#else
#error Accepting new socket connections is not implemented.
#endif

                    // wait until listener is stopped
                    _listenerCompleted.WaitOne();
                }
                catch (ObjectDisposedException)
                {
                    // BeginAccept / AcceptAsync will throw an ObjectDisposedException when the
                    // server is closed before the listener has started accepting connections.
                    //
                    // As we start accepting connection on a separate thread, this is possible
                    // when the listener is stopped right after it was started.

                    // mark listener stopped
                    _listenerCompleted.Set();
                }
                catch (Exception ex)
                {
                    RaiseExceptionEvent(ex);

                    // mark listener stopped
                    _listenerCompleted.Set();
                }
                finally
                {
                    if (Session != null)
                    {
                        Session.ErrorOccured -= Session_ErrorOccured;
                        Session.Disconnected -= Session_Disconnected;
                    }
                }
            });
        }