code: func (s *Session) OpenStream() (*Stream, error) {
  	if s.IsClosed() {
  		return nil, ErrSessionShutdown
  	}
  	if atomic.LoadInt32(&s.remoteGoAway) == 1 {
  		return nil, ErrRemoteGoAway
  	}
  
  	// Block if we have too many inflight SYNs
  	select {
  	case s.synCh <- struct{}{}:
  	case <-s.shutdownCh:
  		return nil, ErrSessionShutdown
  	}
  
  GET_ID:
  	// Get an ID, and check for stream exhaustion
  	id := atomic.LoadUint32(&s.nextStreamID)
  	if id >= math.MaxUint32-1 {
  		return nil, ErrStreamsExhausted
  	}
  	if !atomic.CompareAndSwapUint32(&s.nextStreamID, id, id+2) {
  		goto GET_ID
  	}
  
  	// Register the stream
  	stream := newStream(s, id, streamInit)
  	s.streamLock.Lock()
  	s.streams[id] = stream
  	s.inflight[id] = struct{}{}
  	s.streamLock.Unlock()
  
  	// Send the window update to create
  	if err := stream.sendWindowUpdate(); err != nil {
  		select {
  		case <-s.synCh:
  		default:
  			s.logger.Printf("[ERR] yamux: aborted stream open without inflight syn semaphore")
  		}
  		return nil, err
  	}
  	return stream, nil
  }
docs: // OpenStream is used to create a new stream