/// <summary> /// Upload the files and subdirectories in the specified directory. /// </summary> /// <param name="channel">The channel to perform the upload in.</param> /// <param name="input">A <see cref="Stream"/> from which any feedback from the server can be read.</param> /// <param name="directoryInfo">The directory to upload.</param> private void UploadDirectoryContent(IChannelSession channel, Stream input, DirectoryInfo directoryInfo) { // Upload files var files = directoryInfo.GetFiles(); foreach (var file in files) { using (var source = file.OpenRead()) { UploadTimes(channel, input, file); UploadFileModeAndName(channel, input, source.Length, file.Name); UploadFileContent(channel, input, source, file.Name); } } // Upload directories var directories = directoryInfo.GetDirectories(); foreach (var directory in directories) { UploadTimes(channel, input, directory); UploadDirectoryModeAndName(channel, input, directory.Name); UploadDirectoryContent(channel, input, directory); } // Mark upload of current directory complete SendData(channel, "E\n"); CheckReturnCode(input); }
/// <summary> /// Releases unmanaged and - optionally - managed resources /// </summary> /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> protected virtual void Dispose(bool disposing) { if (_disposed) { return; } if (disposing) { UnsubscribeFromSessionEvents(_session); var channelClosedWaitHandle = _channelClosedWaitHandle; if (channelClosedWaitHandle != null) { channelClosedWaitHandle.Dispose(); _channelClosedWaitHandle = null; } var channel = _channel; if (channel != null) { channel.Dispose(); _channel = null; } var dataReaderTaskCompleted = _dataReaderTaskCompleted; if (dataReaderTaskCompleted != null) { dataReaderTaskCompleted.Dispose(); _dataReaderTaskCompleted = null; } _disposed = true; } }
public void On_Text_State_Changed(object sender, PropertyChangedEventArgs textArgs) { IChannelSession source = (IChannelSession)sender; if (textArgs.PropertyName == "TextState") { switch (source.TextState) { case ConnectionState.Connecting: Debug.Log($"Text Channel Connecting"); break; case ConnectionState.Connected: Debug.Log($"Text Channel Connected"); break; case ConnectionState.Disconnecting: Debug.Log($"Text Channel Disconnecting"); break; case ConnectionState.Disconnected: Debug.Log($"Text Channel Disconnected"); vivox.channelSession.PropertyChanged -= On_Text_State_Changed; break; } } }
private void InternalUpload(IChannelSession channel, Stream input, Stream source, string filename) { var length = source.Length; this.SendData(channel, string.Format("C0644 {0} {1}\n", length, Path.GetFileName(filename))); this.CheckReturnCode(input); var buffer = new byte[this.BufferSize]; var read = source.Read(buffer, 0, buffer.Length); long totalRead = 0; while (read > 0) { this.SendData(channel, buffer, read); totalRead += read; this.RaiseUploadingEvent(filename, length, totalRead); read = source.Read(buffer, 0, buffer.Length); } this.SendConfirmation(channel); this.CheckReturnCode(input); }
private void InternalDownload(IChannelSession channel, Stream input, Stream output, string filename, long length) { var buffer = new byte[Math.Min(length, this.BufferSize)]; var needToRead = length; do { var read = input.Read(buffer, 0, (int)Math.Min(needToRead, this.BufferSize)); output.Write(buffer, 0, read); this.RaiseDownloadingEvent(filename, length, length - needToRead); needToRead -= read; }while (needToRead > 0); output.Flush(); // Raise one more time when file downloaded this.RaiseDownloadingEvent(filename, length, length - needToRead); // Send confirmation byte after last data byte was read this.SendConfirmation(channel); this.CheckReturnCode(input); }
public void On_Channel_Status_Changed(object sender, PropertyChangedEventArgs channelArgs) { IChannelSession source = (IChannelSession)sender; if (channelArgs.PropertyName == "ChannelState") { switch (source.ChannelState) { case ConnectionState.Connecting: Debug.Log("Channel Connecting"); break; case ConnectionState.Connected: Debug.Log($"{source.Channel.Name} Connected"); break; case ConnectionState.Disconnecting: Debug.Log($"{source.Channel.Name} disconnecting"); break; case ConnectionState.Disconnected: Debug.Log($"{source.Channel.Name} disconnected"); Bind_Channel_Callback_Listeners(false, vivox.channelSession); Bind_User_Callbacks(false, vivox.channelSession); Bind_Group_Message_Callbacks(false, vivox.channelSession); break; } } }
private void InternalUpload(IChannelSession channel, Stream input, DirectoryInfo directoryInfo) { // Upload files var files = directoryInfo.GetFiles(); foreach (var file in files) { InternalUpload(channel, input, file, file.Name); } // Upload directories var directories = directoryInfo.GetDirectories(); foreach (var directory in directories) { InternalSetTimestamp(channel, input, directoryInfo.LastWriteTimeUtc, directoryInfo.LastAccessTimeUtc); SendData(channel, string.Format("D0755 0 {0}\n", directory.Name)); CheckReturnCode(input); InternalUpload(channel, input, directory); SendData(channel, "E\n"); CheckReturnCode(input); } }
/// <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; } }
/// <summary> /// Waits for the pending asynchronous command execution to complete. /// </summary> /// <param name="asyncResult">The reference to the pending asynchronous request to finish.</param> /// <returns>Command execution result.</returns> /// <example> /// <code source="..\..\TCMSSH.Tests\Classes\SshCommandTest.cs" region="Example SshCommand CreateCommand BeginExecute IsCompleted EndExecute" language="C#" title="Asynchronous Command Execution" /> /// </example> /// <exception cref="ArgumentException">Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult.</exception> public string EndExecute(IAsyncResult asyncResult) { if (this._asyncResult == asyncResult && this._asyncResult != null) { lock (this._endExecuteLock) { if (this._asyncResult != null) { // Make sure that operation completed if not wait for it to finish this.WaitOnHandle(this._asyncResult.AsyncWaitHandle); if (_channel.IsOpen) { _channel.Close(); } UnsubscribeFromEventsAndDisposeChannel(); _channel = null; _asyncResult = null; return(this.Result); } } } throw new ArgumentException("Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult."); }
/// <summary> /// Releases unmanaged and - optionally - managed resources /// </summary> /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged ResourceMessages.</param> protected virtual void Dispose(bool disposing) { // Check to see if Dispose has already been called. if (!this._disposed) { // If disposing equals true, dispose all managed // and unmanaged ResourceMessages. if (disposing) { if (this._channelClosedWaitHandle != null) { this._channelClosedWaitHandle.Dispose(); this._channelClosedWaitHandle = null; } if (this._channel != null) { this._channel.Dispose(); this._channel = null; } if (this._dataReaderTaskCompleted != null) { this._dataReaderTaskCompleted.Dispose(); this._dataReaderTaskCompleted = null; } } // Note disposing has been done. this._disposed = true; } }
private void CreateChannel() { this._channel = this._session.CreateChannelSession(); this._channel.DataReceived += Channel_DataReceived; this._channel.ExtendedDataReceived += Channel_ExtendedDataReceived; this._channel.RequestReceived += Channel_RequestReceived; this._channel.Closed += Channel_Closed; // Dispose of streams if already exists if (this.OutputStream != null) { this.OutputStream.Dispose(); this.OutputStream = null; } if (this.ExtendedOutputStream != null) { this.ExtendedOutputStream.Dispose(); this.ExtendedOutputStream = null; } // Initialize output streams and StringBuilders this.OutputStream = new PipeStream(); this.ExtendedOutputStream = new PipeStream(); this._result = null; this._error = null; }
/// <summary> /// Releases the unmanaged resources used by the <see cref="T:System.IO.Stream"/> and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { base.Dispose(disposing); if (_isDisposed) { return; } if (disposing) { UnsubscribeFromSessionEvents(_session); if (_channel != null) { _channel.DataReceived -= Channel_DataReceived; _channel.Closed -= Channel_Closed; _channel.Dispose(); _channel = null; } if (_dataReceived != null) { _dataReceived.Dispose(); _dataReceived = null; } _isDisposed = true; } else { UnsubscribeFromSessionEvents(_session); } }
private async void InternalUpload(IChannelSession channel, Stream input, IStorageFolder directoryInfo) { // Upload file var files = await directoryInfo.GetFilesAsync(); foreach (var file in files) { InternalUpload(channel, input, file, file.Name); } // Upload directories var directories = await directoryInfo.GetFoldersAsync(); foreach (var directory in directories) { var directoryProperties = await directory.GetBasicPropertiesAsync(); InternalSetTimestamp(channel, input, directoryProperties.DateModified.DateTime, directoryProperties.DateModified.DateTime); SendData(channel, string.Format("D0755 0 {0}\n", directory.Name)); CheckReturnCode(input); InternalUpload(channel, input, directory); SendData(channel, "E\n"); CheckReturnCode(input); } }
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; }
/// <summary> /// Waits for the pending asynchronous command execution to complete. /// </summary> /// <param name="asyncResult">The reference to the pending asynchronous request to finish.</param> /// <returns>Command execution result.</returns> /// <example> /// <code source="..\..\src\Renci.SshNet.Tests\Classes\SshCommandTest.cs" region="Example SshCommand CreateCommand BeginExecute IsCompleted EndExecute" language="C#" title="Asynchronous Command Execution" /> /// </example> /// <exception cref="ArgumentException">Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult.</exception> /// <exception cref="ArgumentNullException"><paramref name="asyncResult"/> is <c>null</c>.</exception> public string EndExecute(IAsyncResult asyncResult) { if (asyncResult == null) { throw new ArgumentNullException("asyncResult"); } var commandAsyncResult = asyncResult as CommandAsyncResult; if (commandAsyncResult == null || _asyncResult != commandAsyncResult) { throw new ArgumentException(string.Format("The {0} object was not returned from the corresponding asynchronous method on this class.", typeof(IAsyncResult).Name)); } lock (_endExecuteLock) { if (commandAsyncResult.EndCalled) { throw new ArgumentException("EndExecute can only be called once for each asynchronous operation."); } // wait for operation to complete (or time out) WaitOnHandle(_asyncResult.AsyncWaitHandle); UnsubscribeFromEventsAndDisposeChannel(_channel); _channel = null; commandAsyncResult.EndCalled = true; return(Result); } }
/// <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(); }
private void SetupParticipantHandlers() { PositionalGameObject = PositionalGameObject != null ? PositionalGameObject : gameObject; ChannelSession = Participant.ParentChannelSession; Participant.PropertyChanged -= Participant_PropertyChanged; Participant.PropertyChanged += Participant_PropertyChanged; }
private void JoinChannel(string channelName) { if (currentChannelSession != null) { StartCoroutine(this.DisconnectChannel(this.currentChannelSession)); } currentChannelSession = vivoxVoiceManager.JoinChannel(channelName, ChannelType.NonPositional, VivoxVoiceManager.ChatCapability.TextAndAudio); }
private void InternalUpload(IChannelSession channel, Stream input, FileInfo fileInfo, string filename) { InternalSetTimestamp(channel, input, fileInfo.LastWriteTimeUtc, fileInfo.LastAccessTimeUtc); using (var source = fileInfo.OpenRead()) { InternalUpload(channel, input, source, filename); } }
/// <summary> /// Uploads the <see cref="FileSystemInfo.LastWriteTimeUtc"/> and <see cref="FileSystemInfo.LastAccessTimeUtc"/> /// of the next file or directory to upload. /// </summary> /// <param name="channel">The channel to perform the upload in.</param> /// <param name="input">A <see cref="Stream"/> from which any feedback from the server can be read.</param> /// <param name="fileOrDirectory">The file or directory to upload.</param> private void UploadTimes(IChannelSession channel, Stream input, FileSystemInfo fileOrDirectory) { var zeroTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); var modificationSeconds = (long)(fileOrDirectory.LastWriteTimeUtc - zeroTime).TotalSeconds; var accessSeconds = (long)(fileOrDirectory.LastAccessTimeUtc - zeroTime).TotalSeconds; SendData(channel, string.Format("T{0} 0 {1} 0\n", modificationSeconds, accessSeconds)); CheckReturnCode(input); }
/// <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); }
private void InternalSetTimestamp(IChannelSession channel, Stream input, DateTime lastWriteTime, DateTime lastAccessime) { var zeroTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); var modificationSeconds = (long)(lastWriteTime - zeroTime).TotalSeconds; var accessSeconds = (long)(lastAccessime - zeroTime).TotalSeconds; this.SendData(channel, string.Format("T{0} 0 {1} 0\n", modificationSeconds, accessSeconds)); this.CheckReturnCode(input); }
public DefaultVivoxTextChannelSubscribableAdapter([NotNull] IChannelSession channel) { if (channel == null) { throw new ArgumentNullException(nameof(channel)); } channel.MessageLog.AfterItemAdded += MessageLogOnAfterItemAdded; }
private async void InternalUpload(IChannelSession channel, Stream input, IStorageFile fileInfo, string filename) { var fileProperties = await fileInfo.GetBasicPropertiesAsync(); InternalSetTimestamp(channel, input, fileProperties.DateModified.DateTime, fileProperties.DateModified.DateTime); using (var source = await fileInfo.OpenStreamForReadAsync()) { InternalUpload(channel, input, source, filename); } }
private IEnumerator AwaitLobbyRejoin() { IChannelSession lobbyChannel = m_vivoxVoiceManager.ActiveChannels.FirstOrDefault(ac => ac.Channel.Name == LobbyChannelName); // Lets wait until we have left the lobby channel before tyring to join it. yield return(new WaitUntil(() => lobbyChannel == null || (lobbyChannel.AudioState != ConnectionState.Connected && lobbyChannel.TextState != ConnectionState.Connected))); // Always send if hosting, since we could have missed a request. m_vivoxVoiceManager.JoinChannel(LobbyChannelName, ChannelType.NonPositional, VivoxVoiceManager.ChatCapability.TextOnly, false); }
public void Bind_Group_Message_Callbacks(bool bind, IChannelSession channelSesh) { if (bind) { channelSesh.MessageLog.AfterItemAdded += On_Message_Recieved; } else { channelSesh.MessageLog.AfterItemAdded -= On_Message_Recieved; } }
private void BindAudioStatusCallbackListeners(bool bind, IChannelSession channelSess) { if (bind) { channelSess.PropertyChanged += AudioStatus; } else { channelSess.PropertyChanged -= AudioStatus; } }
private void SendData(IChannelSession channel, byte[] buffer, int length) { if (length == buffer.Length) { channel.SendData(buffer); } else { channel.SendData(buffer.Take(length).ToArray()); } }
public TranscribedMessage(AccountId sender, string message, string key, string language, IChannelSession channelSession, bool fromSelf, DateTime?receivedTime = null) { ReceivedTime = receivedTime ?? DateTime.Now; Sender = sender; Message = message; Key = key; Language = language; ChannelSession = channelSession; FromSelf = fromSelf; }
public void Bind_Channel_Callback_Listeners(bool bind, IChannelSession channelSesh) { if (bind) { channelSesh.PropertyChanged += On_Channel_Status_Changed; } else { channelSesh.PropertyChanged -= On_Channel_Status_Changed; } }
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(); }
private void InternalDownload(IChannelSession channel, Stream input, Stream output, string filename, long length) { var buffer = new byte[Math.Min(length, this.BufferSize)]; var needToRead = length; do { var read = input.Read(buffer, 0, (int)Math.Min(needToRead, this.BufferSize)); output.Write(buffer, 0, read); this.RaiseDownloadingEvent(filename, length, length - needToRead); needToRead -= read; } while (needToRead > 0); output.Flush(); // Raise one more time when file downloaded this.RaiseDownloadingEvent(filename, length, length - needToRead); // Send confirmation byte after last data byte was read this.SendConfirmation(channel); this.CheckReturnCode(input); }
partial void SendData(IChannelSession channel, string command) { channel.SendData(Encoding.Default.GetBytes(command)); }
private void SendData(IChannelSession channel, byte[] buffer) { channel.SendData(buffer); }
private void SendConfirmation(IChannelSession channel) { this.SendData(channel, new byte[] { 0 }); }
partial void SendData(IChannelSession channel, string command);
private void Channel_Closed(object sender, ChannelEventArgs e) { if (this.Stopping != null) { // Handle event on different thread this.ExecuteThread(() => this.Stopping(this, new EventArgs())); } if (this._channel.IsOpen) { this._channel.Close(); } this._channelClosedWaitHandle.Set(); this._input.Dispose(); this._input = null; this._dataReaderTaskCompleted.WaitOne(this._session.ConnectionInfo.Timeout); this._dataReaderTaskCompleted.Dispose(); this._dataReaderTaskCompleted = null; this._channel.DataReceived -= Channel_DataReceived; this._channel.ExtendedDataReceived -= Channel_ExtendedDataReceived; this._channel.Closed -= Channel_Closed; this._session.Disconnected -= Session_Disconnected; this._session.ErrorOccured -= Session_ErrorOccured; if (this.Stopped != null) { // Handle event on different thread this.ExecuteThread(() => this.Stopped(this, new EventArgs())); } this._channel = null; }
/// <summary> /// Releases unmanaged and - optionally - managed resources /// </summary> /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged ResourceMessages.</param> protected virtual void Dispose(bool disposing) { // Check to see if Dispose has already been called. if (!this._isDisposed) { // If disposing equals true, dispose all managed // and unmanaged ResourceMessages. if (disposing) { this._session.Disconnected -= Session_Disconnected; this._session.ErrorOccured -= Session_ErrorOccured; // Dispose managed ResourceMessages. if (this.OutputStream != null) { this.OutputStream.Dispose(); this.OutputStream = null; } // Dispose managed ResourceMessages. if (this.ExtendedOutputStream != null) { this.ExtendedOutputStream.Dispose(); this.ExtendedOutputStream = null; } // Dispose managed ResourceMessages. if (this._sessionErrorOccuredWaitHandle != null) { this._sessionErrorOccuredWaitHandle.Dispose(); this._sessionErrorOccuredWaitHandle = null; } // Dispose managed ResourceMessages. if (this._channel != null) { UnsubscribeFromEventsAndDisposeChannel(); this._channel = null; } } // Note disposing has been done. this._isDisposed = true; } }
/// <summary> /// Disconnects the subsystem channel. /// </summary> public void Disconnect() { UnsubscribeFromSessionEvents(_session); var channel = _channel; if (channel != null) { channel.DataReceived -= Channel_DataReceived; channel.Exception -= Channel_Exception; channel.Closed -= Channel_Closed; channel.Close(); channel.Dispose(); _channel = null; } }
/// <summary> /// Releases the unmanaged resources used by the <see cref="T:System.IO.Stream"/> and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { base.Dispose(disposing); if (_isDisposed) return; if (disposing) { UnsubscribeFromSessionEvents(_session); if (_channel != null) { _channel.DataReceived -= Channel_DataReceived; _channel.Closed -= Channel_Closed; _channel.Dispose(); _channel = null; } if (_dataReceived != null) { _dataReceived.Dispose(); _dataReceived = null; } _isDisposed = true; } else { UnsubscribeFromSessionEvents(_session); } }
/// <summary> /// Starts this shell. /// </summary> /// <exception cref="SshException">Shell is started.</exception> public void Start() { if (this.IsStarted) { throw new SshException("Shell is started."); } if (this.Starting != null) { this.Starting(this, new EventArgs()); } this._channel = this._session.CreateChannelSession(); this._channel.DataReceived += Channel_DataReceived; this._channel.ExtendedDataReceived += Channel_ExtendedDataReceived; this._channel.Closed += Channel_Closed; this._session.Disconnected += Session_Disconnected; this._session.ErrorOccured += Session_ErrorOccured; this._channel.Open(); this._channel.SendPseudoTerminalRequest(this._terminalName, this._columns, this._rows, this._width, this._height, this._terminalModes); this._channel.SendShellRequest(); this._channelClosedWaitHandle = new AutoResetEvent(false); // Start input stream listener this._dataReaderTaskCompleted = new ManualResetEvent(false); this.ExecuteThread(() => { try { var buffer = new byte[this._bufferSize]; while (this._channel.IsOpen) { var asyncResult = this._input.BeginRead(buffer, 0, buffer.Length, delegate(IAsyncResult result) { // If input stream is closed and disposed already dont finish reading the stream if (this._input == null) return; var read = this._input.EndRead(result); if (read > 0) { this._channel.SendData(buffer.Take(read).ToArray()); } }, null); EventWaitHandle.WaitAny(new WaitHandle[] { asyncResult.AsyncWaitHandle, this._channelClosedWaitHandle }); if (asyncResult.IsCompleted) continue; break; } } catch (Exception exp) { this.RaiseError(new ExceptionEventArgs(exp)); } finally { this._dataReaderTaskCompleted.Set(); } }); this.IsStarted = true; if (this.Started != null) { this.Started(this, new EventArgs()); } }
/// <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()); } }
private void SendConfirmation(IChannelSession channel, byte errorCode, string message) { this.SendData(channel, new[] { errorCode }); this.SendData(channel, string.Format("{0}\n", message)); }
/// <summary> /// Releases unmanaged and - optionally - managed resources /// </summary> /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> protected virtual void Dispose(bool disposing) { if (_isDisposed) return; if (disposing) { // unsubscribe from session events to ensure other objects that we're going to dispose // are not accessed while disposing var session = _session; if (session != null) { session.Disconnected -= Session_Disconnected; session.ErrorOccured -= Session_ErrorOccured; _session = null; } // unsubscribe from channel events to ensure other objects that we're going to dispose // are not accessed while disposing var channel = _channel; if (channel != null) { UnsubscribeFromEventsAndDisposeChannel(channel); _channel = null; } var outputStream = OutputStream; if (outputStream != null) { outputStream.Dispose(); OutputStream = null; } var extendedOutputStream = ExtendedOutputStream; if (extendedOutputStream != null) { extendedOutputStream.Dispose(); ExtendedOutputStream = null; } var sessionErrorOccuredWaitHandle = _sessionErrorOccuredWaitHandle; if (sessionErrorOccuredWaitHandle != null) { sessionErrorOccuredWaitHandle.Dispose(); _sessionErrorOccuredWaitHandle = null; } _isDisposed = true; } }
/// <summary> /// Releases the unmanaged resources used by the <see cref="T:System.IO.Stream"/> and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { base.Dispose(disposing); if (_session != null) { _session.Disconnected -= Session_Disconnected; _session.ErrorOccured -= Session_ErrorOccured; } if (_channel != null) { _channel.DataReceived -= Channel_DataReceived; _channel.Closed -= Channel_Closed; _channel.Dispose(); _channel = null; } if (_dataReceived != null) { _dataReceived.Dispose(); _dataReceived = null; } }
private void SendData(IChannelSession channel, byte[] buffer, int length) { #if TUNING channel.SendData(buffer, 0, length); #else if (length == buffer.Length) { channel.SendData(buffer); } else { channel.SendData(buffer.Take(length).ToArray()); } #endif }
private void InternalDownload(IChannelSession channel, Stream input, FileSystemInfo fileSystemInfo) { var modifiedTime = DateTime.Now; var accessedTime = DateTime.Now; var startDirectoryFullName = fileSystemInfo.FullName; var currentDirectoryFullName = startDirectoryFullName; var directoryCounter = 0; while (true) { var message = ReadString(input); if (message == "E") { SendConfirmation(channel); // Send reply directoryCounter--; currentDirectoryFullName = new DirectoryInfo(currentDirectoryFullName).Parent.FullName; if (directoryCounter == 0) break; continue; } var match = DirectoryInfoRe.Match(message); if (match.Success) { SendConfirmation(channel); // Send reply // Read directory var mode = long.Parse(match.Result("${mode}")); var filename = match.Result("${filename}"); DirectoryInfo newDirectoryInfo; if (directoryCounter > 0) { newDirectoryInfo = Directory.CreateDirectory(string.Format("{0}{1}{2}", currentDirectoryFullName, Path.DirectorySeparatorChar, filename)); newDirectoryInfo.LastAccessTime = accessedTime; newDirectoryInfo.LastWriteTime = modifiedTime; } else { // Dont create directory for first level newDirectoryInfo = fileSystemInfo as DirectoryInfo; } directoryCounter++; currentDirectoryFullName = newDirectoryInfo.FullName; continue; } match = FileInfoRe.Match(message); if (match.Success) { // Read file SendConfirmation(channel); // Send reply var mode = match.Result("${mode}"); var length = long.Parse(match.Result("${length}")); var fileName = match.Result("${filename}"); var fileInfo = fileSystemInfo as FileInfo; if (fileInfo == null) fileInfo = new FileInfo(string.Format("{0}{1}{2}", currentDirectoryFullName, Path.DirectorySeparatorChar, fileName)); using (var output = fileInfo.OpenWrite()) { InternalDownload(channel, input, output, fileName, length); } fileInfo.LastAccessTime = accessedTime; fileInfo.LastWriteTime = modifiedTime; if (directoryCounter == 0) break; continue; } match = TimestampRe.Match(message); if (match.Success) { // Read timestamp SendConfirmation(channel); // Send reply var mtime = long.Parse(match.Result("${mtime}")); var atime = long.Parse(match.Result("${atime}")); var zeroTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); modifiedTime = zeroTime.AddSeconds(mtime); accessedTime = zeroTime.AddSeconds(atime); continue; } SendConfirmation(channel, 1, string.Format("\"{0}\" is not valid protocol message.", message)); } }
/// <summary> /// Waits for the pending asynchronous command execution to complete. /// </summary> /// <param name="asyncResult">The reference to the pending asynchronous request to finish.</param> /// <returns>Command execution result.</returns> /// <example> /// <code source="..\..\Renci.SshNet.Tests\Classes\SshCommandTest.cs" region="Example SshCommand CreateCommand BeginExecute IsCompleted EndExecute" language="C#" title="Asynchronous Command Execution" /> /// </example> /// <exception cref="ArgumentException">Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult.</exception> public string EndExecute(IAsyncResult asyncResult) { if (this._asyncResult == asyncResult && this._asyncResult != null) { lock (this._endExecuteLock) { if (this._asyncResult != null) { // Make sure that operation completed if not wait for it to finish this.WaitOnHandle(this._asyncResult.AsyncWaitHandle); if (_channel.IsOpen) { _channel.Close(); } UnsubscribeFromEventsAndDisposeChannel(); _channel = null; _asyncResult = null; return this.Result; } } } throw new ArgumentException("Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult."); }
/// <summary> /// Disconnects the subsystem channel. /// </summary> public void Disconnect() { if (_session != null) { _session.ErrorOccured -= Session_ErrorOccured; _session.Disconnected -= Session_Disconnected; } if (_channel != null) { _channel.DataReceived -= Channel_DataReceived; _channel.Exception -= Channel_Exception; _channel.Closed -= Channel_Closed; _channel.Close(); _channel.Dispose(); _channel = null; } }
/// <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(); }
/// <summary> /// Waits for the pending asynchronous command execution to complete. /// </summary> /// <param name="asyncResult">The reference to the pending asynchronous request to finish.</param> /// <returns>Command execution result.</returns> /// <example> /// <code source="..\..\src\Renci.SshNet.Tests\Classes\SshCommandTest.cs" region="Example SshCommand CreateCommand BeginExecute IsCompleted EndExecute" language="C#" title="Asynchronous Command Execution" /> /// </example> /// <exception cref="ArgumentException">Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult.</exception> /// <exception cref="ArgumentNullException"><paramref name="asyncResult"/> is <c>null</c>.</exception> public string EndExecute(IAsyncResult asyncResult) { if (asyncResult == null) { throw new ArgumentNullException("asyncResult"); } var commandAsyncResult = asyncResult as CommandAsyncResult; if (commandAsyncResult == null || _asyncResult != commandAsyncResult) { throw new ArgumentException(string.Format("The {0} object was not returned from the corresponding asynchronous method on this class.", typeof(IAsyncResult).Name)); } lock (_endExecuteLock) { if (commandAsyncResult.EndCalled) { throw new ArgumentException("EndExecute can only be called once for each asynchronous operation."); } // wait for operation to complete (or time out) WaitOnHandle(_asyncResult.AsyncWaitHandle); UnsubscribeFromEventsAndDisposeChannel(_channel); _channel = null; commandAsyncResult.EndCalled = true; return Result; } }
/// <summary> /// Releases unmanaged and - optionally - managed resources /// </summary> /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> protected virtual void Dispose(bool disposing) { if (_disposed) return; if (disposing) { UnsubscribeFromSessionEvents(_session); var channelClosedWaitHandle = _channelClosedWaitHandle; if (channelClosedWaitHandle != null) { channelClosedWaitHandle.Dispose(); _channelClosedWaitHandle = null; } var channel = _channel; if (channel != null) { channel.Dispose(); _channel = null; } var dataReaderTaskCompleted = _dataReaderTaskCompleted; if (dataReaderTaskCompleted != null) { dataReaderTaskCompleted.Dispose(); _dataReaderTaskCompleted = null; } _disposed = true; } }