/** * Process incoming stanza (first-level element). */ void Stream::processStanza(const Parser::Event& event) { QString id = event.element().attribute("id"); if (!id.isEmpty() && d->scb.contains(id)) { Private::StanzaCallback cb = d->scb.value(id); QObject *obj = cb.first; qDebug("[XMPP::Stream] Invoke %s::%s for stanza with id %s", obj->metaObject()->className(), qPrintable(cb.second), qPrintable(id)); QMetaObject::invokeMethod(obj, cb.second.toLocal8Bit().constData(), Q_ARG(XMPP::Stanza, event.element())); d->scb.remove(id); } if ( event.qualifiedName() == "stream:error" ) { handleStreamError(event); } else if ( event.qualifiedName() == "message" ) { emit stanzaMessage(event.element()); } else if ( event.qualifiedName() == "iq" ) { emit stanzaIQ(event.element()); } else if ( event.qualifiedName() == "presence" ) { emit stanzaPresence(event.element()); } else { if (!handleUnknownElement(event)) qDebug("[XMPP::Stream] Unhandled first-level element: %s", qPrintable(event.qualifiedName())); } }
bool XmlProtocol::baseStep(const Parser::Event &pe) { // Basic if(state == SendOpen) { sendTagOpen(); event = ESend; if(incoming) state = Open; else state = RecvOpen; return true; } else if(state == RecvOpen) { if(incoming) state = SendOpen; else state = Open; // note: event will always be DocumentOpen here handleDocOpen(pe); event = ERecvOpen; return true; } else if(state == Open) { QDomElement e; if(pe.type() == Parser::Event::Element) e = pe.element(); return doStep(e); } // Closing else { if(closeWritten) { if(peerClosed) { event = EPeerClosed; return true; } else return handleCloseFinished(); } need = NNotify; notify = NSend; return false; } }
bool XmlProtocol::processStep() { Parser::Event pe; notify = 0; transferItemList.clear(); if(state != Closing && (state == RecvOpen || stepAdvancesParser())) { // if we get here, then it's because we're in some step that advances the parser pe = xml.readNext(); if(!pe.isNull()) { // note: error/close events should be handled for ALL steps, so do them here switch(pe.type()) { case Parser::Event::DocumentOpen: { transferItemList += TransferItem(pe.actualString(), false); //stringRecv(pe.actualString()); break; } case Parser::Event::DocumentClose: { transferItemList += TransferItem(pe.actualString(), false); //stringRecv(pe.actualString()); if(incoming) { sendTagClose(); event = ESend; peerClosed = true; state = Closing; } else { event = EPeerClosed; } return true; } case Parser::Event::Element: { QDomElement e = elemDoc.importNode(pe.element(),true).toElement(); transferItemList += TransferItem(e, false); //elementRecv(pe.element()); break; } case Parser::Event::Error: { if(incoming) { // If we get a parse error during the initial element exchange, // flip immediately into 'open' mode so that we can report an error. if(state == RecvOpen) { sendTagOpen(); state = Open; } return handleError(); } else { event = EError; errorCode = ErrParse; return true; } } } } else { if(state == RecvOpen || stepRequiresElement()) { need = NNotify; notify |= NRecv; return false; } } } return baseStep(pe); }
/** * Handles stream erorrs (\<stream:error/\> element). */ void Stream::handleStreamError(const Parser::Event& event) { d->lastStreamError = StreamError( event.element() ); emit streamError(); }