code: func (stream *Stream) operateWithTimeout(invoke StreamOperation) (*orderer.StepResponse, error) {
  	timer := time.NewTimer(stream.Timeout)
  	defer timer.Stop()
  
  	var operationEnded sync.WaitGroup
  	operationEnded.Add(1)
  
  	responseChan := make(chan struct {
  		res *orderer.StepResponse
  		err error
  	}, 1)
  
  	go func() {
  		defer operationEnded.Done()
  		res, err := invoke()
  		responseChan <- struct {
  			res *orderer.StepResponse
  			err error
  		}{res: res, err: err}
  	}()
  
  	select {
  	case r := <-responseChan:
  		if r.err != nil {
  			stream.Cancel(r.err)
  		}
  		return r.res, r.err
  	case <-timer.C:
  		stream.Logger.Warningf("Stream %d to %s(%s) was forcibly terminated because timeout (%v) expired",
  			stream.ID, stream.NodeName, stream.Endpoint, stream.Timeout)
  		stream.Cancel(errTimeout)
  		// Wait for the operation goroutine to end
  		operationEnded.Wait()
  		return nil, errTimeout
  	}
  }
docs: // operateWithTimeout performs the given operation on the stream, and blocks until the timeout expires.