docs: async def send_data(
          self,
          stream_id: int,
          data: bytes,
          end_stream: bool = False,
      ):
          """Send data, respecting the receiver's flow control instructions. If
          the provided data is larger than the connection's maximum outbound
          frame size, it will be broken into several frames as appropriate.
          """
          if self.closed:
              raise ConnectionClosedError
          stream = self._get_stream(stream_id)
          if stream.closed:
              raise StreamClosedError(stream_id)
  
          remaining = data
          while len(remaining) > 0:
              await asyncio.gather(
                  self._writable.wait(),
                  self._window_open(stream.id),
              )
  
              remaining_size = len(remaining)
              window_size = self._h2.local_flow_control_window(stream.id)
              max_frame_size = self._h2.max_outbound_frame_size
  
              send_size = min(remaining_size, window_size, max_frame_size)
              if send_size == 0:
                  continue
  
              logger.debug(
                  f'[{stream.id}] Sending {send_size} of {remaining_size} '
                  f'bytes (window {window_size}, frame max {max_frame_size})'
              )
  
              to_send = remaining[:send_size]
              remaining = remaining[send_size:]
              end = (end_stream is True and len(remaining) == 0)
  
              self._h2.send_data(stream.id, to_send, end_stream=end)
              self._flush()
  
              if self._h2.local_flow_control_window(stream.id) == 0:
                  stream.window_open.clear()