/// <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); } }