public delegate void CallbackChannelProcessingNeeded(); //the delgate is used, to inform somebody that output processing is needed (in our case the LinkLayer) public Channel(Encodings encoding, Types type, CallbackOutputProcessingNeeded onOutDirty, CallbackChannelProcessingNeeded onChannelDirty) { this.ID = next_id; next_id++; this.encoding = encoding; this.type = type; this.onOutDirty = onOutDirty; this.onChannelDirty = onChannelDirty; this.isLinked = false; // if IN channel or BIDIRECTIONAL channel, generate inbound queue if (this.type != Types.OUT) { this.in_queue = Queue.Synchronized(new Queue()); } // if OUT channel or BIDIRECTIONAL channel, generate inbound queue if (this.type != Types.IN) { this.out_queue = Queue.Synchronized(new Queue()); this.out_queue_backup = Queue.Synchronized(new Queue()); } }
public ProcessChannel(Process process, Stream stream, Encodings encoding, Types type, CallbackOutputProcessingNeeded onOutDirty, CallbackChannelProcessingNeeded onChannelDirty) : base(encoding, type, onOutDirty, onChannelDirty) { this.stream = stream; this.process = process; this.lock_output = new object(); this.bufferedOutBytes = 0; //if this is an out channel, we create a thread permannently reading from the stream if (this.type != Types.IN) { this.accumulation_out = new List <byte>(); this.thread_out = new Thread(new ThreadStart(this.passThruOut)); thread_out.Start(); } }
public StreamChannel(Stream stream, CallbackOutputProcessingNeeded onOutDirty, CallbackChannelProcessingNeeded onChannelDirty, bool passthrough = true, int passthrough_limit = 3000) : base(Channel.Encodings.BYTEARRAY, Channel.Types.BIDIRECTIONAL, onOutDirty, onChannelDirty) { /* * passtrough is a design decission, working like this: * - if the underlying Stream is readable, read operations are done continuous and automatically * - as reading could block, this is handle by a sperate thread * - data read is pushed directly to the channel output queue * - if the channel queue grows to passthroug_limit, this processed is paused until * the communication layer responsible for output data processing has dequeued enough * data, to shrink the queue below this limit * * In summary this means data is continueosly sent to the client, as long as it could be read * from the stream. Thus a readable StreamChannel puts load to theLinkLayer permanently (throttled * by the passthrough_limit). Additionally, this means if data isn't processed, buffer grow - this * happens on the other endpoint. * * A different approach would be to read data "on demand". This again would involve much more control * communication. With NetworkStreams in mind, this seems to be the better solution '(hopefully) * * ToDo: * - The channels onClose() method gets called by the client, if the channel is removed from the clients channel list. * Current implementation allows the channel to close the underlying stream object. This is somehow wrong and should be initiated * ba a request of the remote peer (close_stream_request). In order to allow the remote peer to send such a request, it * has to be aware of the fact that the channel has been closed. This isn't the case at the moment, as the peer doesn't get informed about this. * - As there's no communication to the peer, when a channel gets closed, pending channel objects reside on the other endpoit when removed * from this peer. * - as this isn't read on demand, a method has to be found to signal the remote peer if EOF is reached on reading. This could for example * be done by writing an empty stream to the channel output queue (empty payload, the byte signaling that this is data has to be included) */ this.stream = stream; this.passthrough = passthrough; this.passthrough_limit = passthrough_limit; //if we have a readable stream and passtrough is enabled, we create a thread to passthrough data read if (stream.CanRead && this.passthrough) { this.passtrough_limit_not_reached = new ManualResetEvent(true); this.thread_out = new Thread(new ThreadStart(this.passThruOut)); thread_out.Start(); } else if (stream.CanRead && !this.passthrough) { // prepare read buffer this.readbuf = new byte[60000]; } Console.WriteLine(String.Format("StreamChannel created {0}, passthrough: {1}", this.ID, passthrough)); }