Exemplo n.º 1
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();
                }
            });
        }
Exemplo n.º 2
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());
            }
        }
Exemplo n.º 3
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);
        }
Exemplo n.º 4
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();
            });
        }
Exemplo n.º 5
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
                    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;
                    }
                }
            });
        }
Exemplo n.º 6
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));
        }