<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def send(self, stanza, *, timeout=None, cb=None):
 """ Send a stanza. :param stanza: Stanza to send :type stanza: :class:`~.IQ`, :class:`~.Presence` or :class:`~.Message` :param timeout: Maximum time in seconds to wait for an IQ response, or :data:`None` to disable the timeout. :type timeout: :class:`~numbers.Real` or :data:`None` :param cb: Optional callback which is called synchronously when the reply is received (IQ requests only!) :raise OSError: if the underlying XML stream fails and stream management is not disabled. :raise aioxmpp.stream.DestructionRequested: if the stream is closed while sending the stanza or waiting for a response. :raise aioxmpp.errors.XMPPError: if an error IQ response is received :raise aioxmpp.errors.ErroneousStanza: if the IQ response could not be parsed :raise ValueError: if `cb` is given and `stanza` is not an IQ request. :return: IQ response :attr:`~.IQ.payload` or :data:`None` Send the stanza and wait for it to be sent. If the stanza is an IQ request, the response is awaited and the :attr:`~.IQ.payload` of the response is returned. If the stream is currently not ready, this method blocks until the stream is ready to send payload stanzas. Note that this may be before initial presence has been sent. To synchronise with that type of events, use the appropriate signals. The `timeout` as well as any of the exception cases referring to a "response" do not apply for IQ response stanzas, message stanzas or presence stanzas sent with this method, as this method only waits for a reply if an IQ *request* stanza is being sent. If `stanza` is an IQ request and the response is not received within `timeout` seconds, :class:`TimeoutError` (not :class:`asyncio.TimeoutError`!) is raised. If `cb` is given, `stanza` must be an IQ request (otherwise, :class:`ValueError` is raised before the stanza is sent). It must be a callable returning an awaitable. It receives the response stanza as first and only argument. The returned awaitable is awaited by :meth:`send` and the result is returned instead of the original payload. `cb` is called synchronously from the stream handling loop when the response is received, so it can benefit from the strong ordering guarantees given by XMPP XML Streams. The `cb` may also return :data:`None`, in which case :meth:`send` will simply return the IQ payload as if `cb` was not given. Since the return value of coroutine functions is awaitable, it is valid and supported to pass a coroutine function as `cb`. .. warning:: Remember that it is an implementation detail of the event loop when a coroutine is scheduled after it awaited an awaitable; this implies that if the caller of :meth:`send` is merely awaiting the :meth:`send` coroutine, the strong ordering guarantees of XMPP XML Streams are lost. To regain those, use the `cb` argument. .. note:: For the sake of readability, unless you really need the strong ordering guarantees, avoid the use of the `cb` argument. Avoid using a coroutine function unless you really need to. .. versionchanged:: 0.10 * This method now waits until the stream is ready to send stanza¸ payloads. * This method was moved from :meth:`aioxmpp.stream.StanzaStream.send`. .. versionchanged:: 0.9 The `cb` argument was added. .. versionadded:: 0.8 """

        if not self.running:
            raise ConnectionError("client is not running")

        if not self.established:
            self.logger.debug("send(%s): stream not established, waiting",
                              stanza)
            # wait for the stream to be established
            stopped_fut = self.on_stopped.future()
            failure_fut = self.on_failure.future()
            established_fut = asyncio.ensure_future(
                self.established_event.wait()
            )
            done, pending = yield from asyncio.wait(
                [
                    established_fut,
                    failure_fut,
                    stopped_fut,
                ],
                return_when=asyncio.FIRST_COMPLETED,
            )
            if not established_fut.done():
                established_fut.cancel()
            if failure_fut.done():
                if not stopped_fut.done():
                    stopped_fut.cancel()
                failure_fut.exception()
                raise ConnectionError("client failed to connect")
            if stopped_fut.done():
                raise ConnectionError("client shut down by user request")

            self.logger.debug("send(%s): stream established, sending")

        return (yield from self.stream._send_immediately(stanza,
                                                         timeout=timeout,
                                                         cb=cb))