Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combine two one-way streams into a two-way stream

In particular I am using a Ionic.Zlib.ZlibStream to do Zlib compression on a System.Net.Sockets.NetworkStream.

Problem is, ZlibStream is a one-way stream; you can Read() or Write() but not both. You need two separate streams, one for sending and one for receiving (one compressing and the other decompressing). Which works fine until you need to pass it to functions that are expecting a single two-way stream (both Read() and Write() functionality). For example, new System.Net.Security.SslStream(Stream base).

I realize I can write a Stream class that takes a writing-stream and a reading-stream and calls the correct stream in the overrides. But I was hoping this already exists in the framework somewhere or there was an implementation already available.

like image 377
Nick Whaley Avatar asked Nov 24 '25 14:11

Nick Whaley


1 Answers

Easy enough if it does not already exist in the framework.

    public class StreamRWJoin : Stream {
        public Stream WriteStream { get; set; }
        public Stream ReadStream { get; set; }
        private bool leaveOpen;

        public StreamRWJoin(Stream readfrom, Stream writeto, bool leaveOpen = false) {
            WriteStream = writeto; ReadStream = readfrom;
            this.leaveOpen = leaveOpen;
        }

        public override bool CanRead {
            get { return ReadStream.CanRead; }
        }

        public override bool CanSeek {
            get { return false; }
        }

        public override bool CanWrite {
            get { return WriteStream.CanWrite; }
        }

        public override void Flush() {
            WriteStream.Flush();
        }

        public override long Length {
            get { throw new NotImplementedException(); }
        }

        public override long Position {
            get {
                throw new NotImplementedException();
            }
            set {
                throw new NotImplementedException();
            }
        }

        public override int Read(byte[] buffer, int offset, int count) {
            return ReadStream.Read(buffer, offset, count);
        }

        public override long Seek(long offset, SeekOrigin origin) {
            throw new NotImplementedException();
        }

        public override void SetLength(long value) {
            throw new NotImplementedException();
        }

        public override void Write(byte[] buffer, int offset, int count) {
            WriteStream.Write(buffer, offset, count);
        }

        public override void Close() {
            if (!leaveOpen)
                try {
                    WriteStream.Close();
                } finally {
                    ReadStream.Close();
                }
        }

        public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) {
            return ReadStream.BeginRead(buffer, offset, count, callback, state);
        }
        public override int EndRead(IAsyncResult asyncResult) {
            return ReadStream.EndRead(asyncResult);
        }

        public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) {
            return WriteStream.BeginWrite(buffer, offset, count, callback, state);
        }
        public override void EndWrite(IAsyncResult asyncResult) {
            WriteStream.EndWrite(asyncResult);
        }

        public override int ReadByte() {
            return ReadStream.ReadByte();
        }
        public override void WriteByte(byte value) {
            ReadStream.WriteByte(value);
        }

        public override int ReadTimeout {
            get {
                return ReadStream.ReadTimeout;
            }
            set {
                ReadStream.ReadTimeout = value;
            }
        }

        public override int WriteTimeout {
            get {
                return WriteStream.WriteTimeout;
            }
            set {
                WriteStream.WriteTimeout = value;
            }
        }

        public override bool CanTimeout {
            get {
                return ReadStream.CanTimeout || WriteStream.CanTimeout;
            }
        }

        public override int GetHashCode() {
            return ReadStream.GetHashCode() ^ WriteStream.GetHashCode();
        }

        protected override void Dispose(bool disposing) {
            if (disposing && !leaveOpen) {
                try {
                    ReadStream.Dispose();
                } finally {
                    WriteStream.Dispose();
                }
            }
        }

        public override string ToString() {
            return "Read: " + ReadStream.ToString() + ", Write: " + WriteStream.ToString();
        }
    }
like image 148
Nick Whaley Avatar answered Nov 27 '25 03:11

Nick Whaley



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!