def _sendDeferred(self, stanza):
        def onResponse(element):
            if element.getAttribute('type') == 'error':
                d.errback(error.exceptionFromStanza(element))
            else:
                d.callback(UserPresence.fromElement(element))

        def onTimeout():
            d.errback(xmlstream.TimeoutError("Timeout waiting for response."))

        def cancelTimeout(result):
            if call.active():
                call.cancel()

            return result

        def recordOccupant(presence):
            occupantJID = presence.sender
            roomJID = occupantJID.userhostJID()
            self._roomOccupantMap[roomJID] = occupantJID
            return presence

        call = self._reactor.callLater(DEFER_TIMEOUT, onTimeout)

        d = defer.Deferred()
        d.addBoth(cancelTimeout)
        d.addCallback(recordOccupant)

        query = "/presence[@from='%s' or (@from='%s' and @type='error')]" % (
                stanza.recipient.full(), stanza.recipient.userhost())
        self.xmlstream.addOnetimeObserver(query, onResponse, priority=-1)
        self.xmlstream.send(stanza.toElement())
        return d
Send presence stanza, adding a deferred with a timeout.
dataset/ETHPy150Open ralphm/wokkel/wokkel/muc.py/MUCClientProtocol._sendDeferred