code: func (s *Stream) write(b []byte) (n int, err error) {
  	var flags uint16
  	var max uint32
  	var body io.Reader
  START:
  	s.stateLock.Lock()
  	switch s.state {
  	case streamLocalClose:
  		fallthrough
  	case streamClosed:
  		s.stateLock.Unlock()
  		return 0, ErrStreamClosed
  	case streamReset:
  		s.stateLock.Unlock()
  		return 0, ErrConnectionReset
  	}
  	s.stateLock.Unlock()
  
  	// If there is no data available, block
  	window := atomic.LoadUint32(&s.sendWindow)
  	if window == 0 {
  		goto WAIT
  	}
  
  	// Determine the flags if any
  	flags = s.sendFlags()
  
  	// Send up to our send window
  	max = min(window, uint32(len(b)))
  	body = bytes.NewReader(b[:max])
  
  	// Send the header
  	s.sendHdr.encode(typeData, flags, s.id, max)
  	if err = s.session.waitForSendErr(s.sendHdr, body, s.sendErr); err != nil {
  		return 0, err
  	}
  
  	// Reduce our send window
  	atomic.AddUint32(&s.sendWindow, ^uint32(max-1))
  
  	// Unlock
  	return int(max), err
  
  WAIT:
  	var timeout <-chan time.Time
  	writeDeadline := s.writeDeadline.Load().(time.Time)
  	if !writeDeadline.IsZero() {
  		delay := writeDeadline.Sub(time.Now())
  		timeout = time.After(delay)
  	}
  	select {
  	case <-s.sendNotifyCh:
  		goto START
  	case <-timeout:
  		return 0, ErrTimeout
  	}
  	return 0, nil
  }
docs: // write is used to write to the stream, may return on
  // a short write.