/// <summary> /// Initialize the channel. /// </summary> /// <param name="manager"></param> /// <param name="channelid"></param> /// <param name="context"></param> protected internal virtual void Init(SSHPacketRouter manager, int channelid, SSHContext context) { this.channelid = channelid; this.manager = manager; this.ms = new SSHPacketStore(manager, this, "Channel " + channelid); this.context = context; FireEvent(this, ChannelState.INITIALIZED); }
/// <summary> /// Create a router /// </summary> /// <param name="reader"></param> /// <param name="maxChannels"></param> /// <param name="buffered"></param> public SSHPacketRouter(SSHPacketReader reader, int maxChannels, bool buffered) { this.reader = reader; this.channels = new SSHAbstractChannel[maxChannels]; this.global = new SSHPacketStore(this, null, "Global"); this.sync = new ThreadSynchronizer(buffered); this.buffered = buffered; }
/// <summary> /// Get the next message from the <see cref="Maverick.SSH.Packets.SSHPacketRouter"/> that matches one of the /// ids supplied in the message filter and return its index in the channels message store. /// </summary> /// <param name="channel"></param> /// <param name="observer"></param> /// <returns></returns> protected internal SSHPacket NextMessage(SSHAbstractChannel channel, PacketObserver observer) { SSHPacketStore store = channel == null? global : channel.MessageStore; PacketHolder holder = new PacketHolder(); while (!store.Closed && holder.msg == null) { // Check for an error from the buffering thread if (buffered) { if (!isClosing) { if (lastError != null) { if (lastError is SSHException) { throw lastError; } else { throw new SSHException(lastError); } } } } if (sync.RequestBlock(store, observer, holder)) { try { BlockForMessage(); } finally { // Release the block so that other threads may block or return with the // newly arrived message sync.ReleaseBlock(); } } } return(holder.msg); }
/// <summary> /// Request to obtain the real block but check for messages first in the packet store. /// </summary> /// <param name="store"></param> /// <param name="observer"></param> /// <param name="holder"></param> /// <returns></returns> public bool RequestBlock(SSHPacketStore store, PacketObserver observer, PacketHolder holder) { lock (this) { //#if DEBUG // System.Diagnostics.Trace.WriteLine(System.Threading.Thread.CurrentThread.Name + ": Obtained lock on sync"); //#endif if ((holder.msg = store.HasMessage(observer)) != null) { //#if DEBUG // System.Diagnostics.Trace.WriteLine(System.Threading.Thread.CurrentThread.Name + ": w00t I've found a message"); //#endif return(false); } bool canBlock = !isBlocking; if (canBlock) { //#if DEBUG // System.Diagnostics.Trace.WriteLine(System.Threading.Thread.CurrentThread.Name + ": w00t I've got the *real* block"); //#endif isBlocking = true; } else { //#if DEBUG // System.Diagnostics.Trace.WriteLine(System.Threading.Thread.CurrentThread.Name + ": :( Waiting on sync in pseudo block"); //#endif System.Threading.Monitor.Wait(this); } //#if DEBUG // System.Diagnostics.Trace.WriteLine(System.Threading.Thread.CurrentThread.Name + ": Exiting RequestBlock"); //#endif return(canBlock); } }
private bool BlockForMessage() { SSHPacket packet = reader.NextMessage(); #if DEBUG System.Diagnostics.Trace.WriteLine("Received message id " + packet.MessageID); #endif if (IsChannelMessage(packet.MessageID)) { packet = new SSHChannelMessage(packet); } // Determine the destination channel (if any) SSHAbstractChannel destination = null; if (packet is SSHChannelMessage) { destination = channels[((SSHChannelMessage)packet).ChannelID]; } // Call the destination so that they may process the message bool processed = destination == null ? ProcessGlobalMessage(packet) : destination.ProcessChannelMessage((SSHChannelMessage)packet); // If the previous call did not process the message then add to the // destinations message store if (!processed) { SSHPacketStore ms = destination == null? global : destination.MessageStore; //#if DEBUG // System.Diagnostics.Trace.WriteLine("Adding message " + packet.MessageID + " to store " + ms.ToString() ); //#endif ms.AddMessage(packet); } return(!processed); }