func (s *Stream) setClosed(err error, rd io.Reader) {
	s.closeOnce.Do(func() {
		s.closeErr = err
		s.closeRd = rd
		close(s.closeCh)
	})
}
setClosed is called from Conn goroutine.
package quic
import (
	"io"
	"net"
	"os"
	"sync"
	"time"
)
type Stream struct {
	id   uint64
	conn *Conn
	wrMu sync.Mutex
	wrCh chan io.Writer
	wrDl deadlineTimer
	rdMu sync.Mutex
	rdCh chan io.Reader
	rdDl deadlineTimer
	clMu sync.Mutex
	clCh chan error
	closeOnce sync.Once
	closeCh   chan struct{}
	closeErr error
	closeRd  io.Reader
}
var (
	_ net.Conn = (*Stream)(nil)
)
func newStream(conn *Conn, id uint64) *Stream {
	s := &Stream{
		conn:    conn,
		id:      id,
		wrCh:    make(chan io.Writer),
		rdCh:    make(chan io.Reader),
		clCh:    make(chan error),
		closeCh: make(chan struct{}),
	}
	s.wrDl.init()
	s.rdDl.init()
	return s
}
func (s *Stream) Write(b []byte) (int, error) {
	select {
	case <-s.closeCh:
		return 0, s.closeErr
	default:
		s.wrMu.Lock()
		defer s.wrMu.Unlock()
		return s.writeLocked(b)
	}
}
func (s *Stream) writeLocked(b []byte) (n int, err error) {
	cmd := connCommand{
		cmd: cmdStreamWrite,
		id:  s.id,
	}
	select {
	case <-s.closeCh:
		err = s.closeErr
		return
	case <-s.wrDl.ch:
		err = os.ErrDeadlineExceeded
		return
	case s.conn.cmdCh <- cmd:
		for {
			select {
			case <-s.closeCh:
				err = s.closeErr
				return
			case <-s.wrDl.ch:
				err = os.ErrDeadlineExceeded
				return
			case w := <-s.wrCh:
				var m int
				m, err = w.Write(b[n:])
				s.wrCh <- nil  
				n += m
				if err != nil || n >= len(b) {
					return
				}
			}
		}
	}
}
func (s *Stream) Read(b []byte) (int, error) {
	s.rdMu.Lock()
	defer s.rdMu.Unlock()
	select {
	case <-s.closeCh:
		return s.readClosed(b)
	default:
		return s.readLocked(b)
	}
}
func (s *Stream) readLocked(b []byte) (n int, err error) {
	cmd := connCommand{
		cmd: cmdStreamRead,
		id:  s.id,
	}
	select {
	case <-s.closeCh:
		return s.readClosed(b)
	case <-s.rdDl.ch:
		err = os.ErrDeadlineExceeded
		return
	case s.conn.cmdCh <- cmd:
		for {
			select {
			case <-s.closeCh:
				if n > 0 {
					return n, nil
				}
				return s.readClosed(b)
			case <-s.rdDl.ch:
				err = os.ErrDeadlineExceeded
				return
			case r := <-s.rdCh:
				n, err = r.Read(b)
				s.rdCh <- nil  
				if err != nil || n > 0 || len(b) == 0 {
					return
				}
			}
		}
	}
}
func (s *Stream) readClosed(b []byte) (int, error) {
	if s.closeRd == nil {
		return 0, s.closeErr
	}
	n, err := s.closeRd.Read(b)
	if err == nil && n == 0 {
		err = s.closeErr
	}
	return n, err
}
func (s *Stream) Close() error {
	return s.close(cmdStreamClose, 0)
}
func (s *Stream) CloseWrite(errorCode uint64) error {
	return s.close(cmdStreamCloseWrite, errorCode)
}
func (s *Stream) CloseRead(errorCode uint64) error {
	return s.close(cmdStreamCloseRead, errorCode)
}
func (s *Stream) LocalAddr() net.Addr {
	return s.conn.LocalAddr()
}
func (s *Stream) RemoteAddr() net.Addr {
	return s.conn.RemoteAddr()
}
func (s *Stream) SetDeadline(t time.Time) error {
	s.SetWriteDeadline(t)
	s.SetReadDeadline(t)
	return nil
}
func (s *Stream) SetWriteDeadline(t time.Time) error {
	s.wrMu.Lock()
	s.wrDl.setDeadline(t)
	s.wrMu.Unlock()
	return nil
}
func (s *Stream) SetReadDeadline(t time.Time) error {
	s.rdMu.Lock()
	s.rdDl.setDeadline(t)
	s.rdMu.Unlock()
	return nil
}
func (s *Stream) close(comm command, errorCode uint64) error {
	select {
	case <-s.closeCh:
		return s.closeErr
	default:
	}
	s.clMu.Lock()
	defer s.clMu.Unlock()
	cmd := connCommand{
		cmd: comm,
		id:  s.id,
		n:   errorCode,
	}
	select {
	case <-s.closeCh:
		return s.closeErr
	case s.conn.cmdCh <- cmd:
		select {
		case <-s.closeCh:
			return s.closeErr
		case err := <-s.clCh:
			return err
		}
	}
}
func (s *Stream) sendWriter(w io.Writer) {
	select {
	case s.wrCh <- w:
		<-s.wrCh  
	default:
	}
}
func (s *Stream) sendReader(w io.Reader) {
	select {
	case s.rdCh <- w:
		<-s.rdCh  
	default:
	}
}
func (s *Stream) sendCloseResult(err error) {
	select {
	case <-s.closeCh:
	case s.clCh <- err:
	}
}