func (s *Stream) tryRead(b []byte) (n int, err error) {
	if s.sess.config.Version == 2 {
		return s.tryReadv2(b)
	}
	if len(b) == 0 {
		return 0, nil
	}
	s.bufferLock.Lock()
	if len(s.buffers) > 0 {
		n = copy(b, s.buffers[0])
		s.buffers[0] = s.buffers[0][n:]
		if len(s.buffers[0]) == 0 {
			s.buffers[0] = nil
			s.buffers = s.buffers[1:]
			defaultAllocator.Put(s.heads[0])
			s.heads = s.heads[1:]
		}
	}
	s.bufferLock.Unlock()
	if n > 0 {
		s.sess.returnTokens(n)
		return n, nil
	}
	select {
	case <-s.die:
		return 0, io.EOF
	default:
		return 0, ErrWouldBlock
	}
}
tryRead is the nonblocking version of Read
package smux
import (
	"encoding/binary"
	"io"
	"net"
	"sync"
	"sync/atomic"
	"time"
)
type Stream struct {
	id   uint32
	sess *Session
	buffers [][]byte
	heads   [][]byte  
	bufferLock sync.Mutex
	frameSize  int
	chReadEvent chan struct{}
	die     chan struct{}
	dieOnce sync.Once
	chFinEvent   chan struct{}
	finEventOnce sync.Once
	readDeadline  atomic.Value
	writeDeadline atomic.Value
	numRead    uint32  
	numWritten uint32  
	incr       uint32  
	peerConsumed uint32         
	peerWindow   uint32         
	chUpdate     chan struct{}  
}
func newStream(id uint32, frameSize int, sess *Session) *Stream {
	s := new(Stream)
	s.id = id
	s.chReadEvent = make(chan struct{}, 1)
	s.chUpdate = make(chan struct{}, 1)
	s.frameSize = frameSize
	s.sess = sess
	s.die = make(chan struct{})
	s.chFinEvent = make(chan struct{})
	s.peerWindow = initialPeerWindow  
	return s
}
func (s *Stream) ID() uint32 {
	return s.id
}
func (s *Stream) Read(b []byte) (n int, err error) {
	for {
		n, err = s.tryRead(b)
		if err == ErrWouldBlock {
			if ew := s.waitRead(); ew != nil {
				return 0, ew
			}
		} else {
			return n, err
		}
	}
}