func (s *Stream) sessionClose() {
	s.dieLock.Lock()
	defer s.dieLock.Unlock()
	select {
	case <-s.die:
	default:
		close(s.die)
	}
}
session closes the stream
package smux
import (
	"bytes"
	"io"
	"net"
	"sync"
	"sync/atomic"
	"time"
)
type Stream struct {
	id            uint32
	rstflag       int32
	sess          *Session
	buffer        bytes.Buffer
	bufferLock    sync.Mutex
	frameSize     int
	chReadEvent   chan struct{}  
	die           chan struct{}  
	dieLock       sync.Mutex
	readDeadline  atomic.Value
	writeDeadline atomic.Value
}
func newStream(id uint32, frameSize int, sess *Session) *Stream {
	s := new(Stream)
	s.id = id
	s.chReadEvent = make(chan struct{}, 1)
	s.frameSize = frameSize
	s.sess = sess
	s.die = make(chan struct{})
	return s
}
func (s *Stream) ID() uint32 {
	return s.id
}
func (s *Stream) Read(b []byte) (n int, err error) {
	var deadline <-chan time.Time
	if d, ok := s.readDeadline.Load().(time.Time); ok && !d.IsZero() {
		timer := time.NewTimer(d.Sub(time.Now()))
		defer timer.Stop()
		deadline = timer.C
	}
READ:
	s.bufferLock.Lock()
	n, err = s.buffer.Read(b)
	s.bufferLock.Unlock()
	if n > 0 {
		s.sess.returnTokens(n)
		return n, nil
	} else if atomic.LoadInt32(&s.rstflag) == 1 {
		_ = s.Close()
		return 0, io.EOF
	}
	select {
	case <-s.chReadEvent:
		goto READ
	case <-deadline:
		return n, errTimeout
	case <-s.die:
		return 0, errBrokenPipe
	}
}
func (s *Stream) Write(b []byte) (int, error) {
	var deadline time.Time
	if d, ok := s.writeDeadline.Load().(time.Time); ok && !d.IsZero() {
		deadline = d
	}
	select {
	case <-s.die:
		return 0, errBrokenPipe
	default:
	}
	frames := s.split(b, cmdPSH, s.id)
	sent := 0  
	for k := range frames {
		n, err := s.sess.writeFrame(frames[k], deadline)
		sent += n
		if err != nil {
			return sent, err
		}
	}
	return sent, nil
}
func (s *Stream) Close() error {
	s.dieLock.Lock()
	select {
	case <-s.die:
		s.dieLock.Unlock()
		return errBrokenPipe
	default:
		close(s.die)
		s.dieLock.Unlock()
		s.sess.streamClosed(s.id)
		_, err := s.sess.writeFrame(newFrame(cmdFIN, s.id), time.Now().Add(s.sess.config.WriteTimeout))
		return err
	}
}
func (s *Stream) SetReadDeadline(t time.Time) error {
	s.readDeadline.Store(t)
	return nil
}
func (s *Stream) SetWriteDeadline(t time.Time) error {
	s.writeDeadline.Store(t)
	return nil
}
func (s *Stream) SetDeadline(t time.Time) error {
	if err := s.SetReadDeadline(t); err != nil {
		return err
	}
	if err := s.SetWriteDeadline(t); err != nil {
		return err
	}
	return nil
}