diff options
Diffstat (limited to 'kopete/protocols/jabber/libiris/iris/xmpp-core/protocol.h')
-rw-r--r-- | kopete/protocols/jabber/libiris/iris/xmpp-core/protocol.h | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/kopete/protocols/jabber/libiris/iris/xmpp-core/protocol.h b/kopete/protocols/jabber/libiris/iris/xmpp-core/protocol.h new file mode 100644 index 00000000..8511ce32 --- /dev/null +++ b/kopete/protocols/jabber/libiris/iris/xmpp-core/protocol.h @@ -0,0 +1,355 @@ +/* + * protocol.h - XMPP-Core protocol state machine + * Copyright (C) 2004 Justin Karneges + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef PROTOCOL_H +#define PROTOCOL_H + +#include<qpair.h> +#include"xmlprotocol.h" +#include"xmpp.h" + +#define NS_ETHERX "http://etherx.jabber.org/streams" +#define NS_CLIENT "jabber:client" +#define NS_SERVER "jabber:server" +#define NS_DIALBACK "jabber:server:dialback" +#define NS_STREAMS "urn:ietf:params:xml:ns:xmpp-streams" +#define NS_TLS "urn:ietf:params:xml:ns:xmpp-tls" +#define NS_SASL "urn:ietf:params:xml:ns:xmpp-sasl" +#define NS_SESSION "urn:ietf:params:xml:ns:xmpp-session" +#define NS_STANZAS "urn:ietf:params:xml:ns:xmpp-stanzas" +#define NS_BIND "urn:ietf:params:xml:ns:xmpp-bind" +#define NS_XHTML_IM "http://jabber.org/protocol/xhtml-im" +#define NS_XHTML "http://www.w3.org/1999/xhtml" +#define NS_CHATSTATES "http://jabber.org/protocol/chatstates" + +namespace XMPP +{ + class Version + { + public: + Version(int maj=0, int min=0); + + int major, minor; + }; + + class StreamFeatures + { + public: + StreamFeatures(); + + bool tls_supported, sasl_supported, bind_supported; + bool tls_required; + QStringList sasl_mechs; + }; + + class BasicProtocol : public XmlProtocol + { + public: + // xmpp 1.0 error conditions + enum SASLCond { + Aborted, + IncorrectEncoding, + InvalidAuthzid, + InvalidMech, + MechTooWeak, + NotAuthorized, + TemporaryAuthFailure + }; + enum StreamCond { + BadFormat, + BadNamespacePrefix, + Conflict, + ConnectionTimeout, + HostGone, + HostUnknown, + ImproperAddressing, + InternalServerError, + InvalidFrom, + InvalidId, + InvalidNamespace, + InvalidXml, + StreamNotAuthorized, + PolicyViolation, + RemoteConnectionFailed, + ResourceConstraint, + RestrictedXml, + SeeOtherHost, + SystemShutdown, + UndefinedCondition, + UnsupportedEncoding, + UnsupportedStanzaType, + UnsupportedVersion, + XmlNotWellFormed + }; + enum BindCond { + BindBadRequest, + BindNotAllowed, + BindConflict + }; + + // extend the XmlProtocol enums + enum Need { + NSASLMechs = XmlProtocol::NCustom, // need SASL mechlist + NStartTLS, // need to switch on TLS layer + NSASLFirst, // need SASL first step + NSASLNext, // need SASL next step + NSASLLayer, // need to switch on SASL layer + NCustom = XmlProtocol::NCustom+10 + }; + enum Event { + EFeatures = XmlProtocol::ECustom, // breakpoint after features packet is received + ESASLSuccess, // breakpoint after successful sasl auth + EStanzaReady, // a stanza was received + EStanzaSent, // a stanza was sent + EReady, // stream is ready for stanza use + ECustom = XmlProtocol::ECustom+10 + }; + enum Error { + ErrProtocol = XmlProtocol::ErrCustom, // there was an error in the xmpp-core protocol exchange + ErrStream, // <stream:error>, see errCond, errText, and errAppSpec for details + ErrStartTLS, // server refused starttls + ErrAuth, // authorization error. errCond holds sasl condition (or numeric code for old-protocol) + ErrBind, // server refused resource bind + ErrCustom = XmlProtocol::ErrCustom+10 + }; + + BasicProtocol(); + ~BasicProtocol(); + + void reset(); + + // for outgoing xml + QDomDocument doc; + + // sasl-related + QString saslMech() const; + QByteArray saslStep() const; + void setSASLMechList(const QStringList &list); + void setSASLFirst(const QString &mech, const QByteArray &step); + void setSASLNext(const QByteArray &step); + void setSASLAuthed(); + + // send / recv + void sendStanza(const QDomElement &e); + void sendDirect(const QString &s); + void sendWhitespace(); + QDomElement recvStanza(); + + // shutdown + void shutdown(); + void shutdownWithError(int cond, const QString &otherHost=""); + + // <stream> information + QString to, from, id, lang; + Version version; + + // error output + int errCond; + QString errText; + QDomElement errAppSpec; + QString otherHost; + + QByteArray spare; // filled with unprocessed data on NStartTLS and NSASLLayer + + bool isReady() const; + + enum { TypeElement, TypeStanza, TypeDirect, TypePing }; + + protected: + static int stringToSASLCond(const QString &s); + static int stringToStreamCond(const QString &s); + static QString saslCondToString(int); + static QString streamCondToString(int); + + void send(const QDomElement &e, bool clip=false); + void sendStreamError(int cond, const QString &text="", const QDomElement &appSpec=QDomElement()); + void sendStreamError(const QString &text); // old-style + + bool errorAndClose(int cond, const QString &text="", const QDomElement &appSpec=QDomElement()); + bool error(int code); + void delayErrorAndClose(int cond, const QString &text="", const QDomElement &appSpec=QDomElement()); + void delayError(int code); + + // reimplemented + QDomElement docElement(); + void handleDocOpen(const Parser::Event &pe); + bool handleError(); + bool handleCloseFinished(); + bool doStep(const QDomElement &e); + void itemWritten(int id, int size); + + virtual QString defaultNamespace(); + virtual QStringList extraNamespaces(); // stringlist: prefix,uri,prefix,uri, [...] + virtual void handleStreamOpen(const Parser::Event &pe); + virtual bool doStep2(const QDomElement &e)=0; + + void setReady(bool b); + + QString sasl_mech; + QStringList sasl_mechlist; + QByteArray sasl_step; + bool sasl_authed; + + QDomElement stanzaToRecv; + + private: + struct SASLCondEntry + { + const char *str; + int cond; + }; + static SASLCondEntry saslCondTable[]; + + struct StreamCondEntry + { + const char *str; + int cond; + }; + static StreamCondEntry streamCondTable[]; + + struct SendItem + { + QDomElement stanzaToSend; + QString stringToSend; + bool doWhitespace; + }; + QValueList<SendItem> sendList; + + bool doShutdown, delayedError, closeError, ready; + int stanzasPending, stanzasWritten; + + void init(); + void extractStreamError(const QDomElement &e); + }; + + class CoreProtocol : public BasicProtocol + { + public: + enum { + NPassword = NCustom, // need password for old-mode + EDBVerify = ECustom, // breakpoint after db:verify request + ErrPlain = ErrCustom // server only supports plain, but allowPlain is false locally + }; + + CoreProtocol(); + ~CoreProtocol(); + + void reset(); + + void startClientOut(const Jid &jid, bool oldOnly, bool tlsActive, bool doAuth); + void startServerOut(const QString &to); + void startDialbackOut(const QString &to, const QString &from); + void startDialbackVerifyOut(const QString &to, const QString &from, const QString &id, const QString &key); + void startClientIn(const QString &id); + void startServerIn(const QString &id); + + void setLang(const QString &s); + void setAllowTLS(bool b); + void setAllowBind(bool b); + void setAllowPlain(bool b); // old-mode + + void setPassword(const QString &s); + void setFrom(const QString &s); + void setDialbackKey(const QString &s); + + // input + QString user, host; + + // status + bool old; + + StreamFeatures features; + + //static QString xmlToString(const QDomElement &e, bool clip=false); + + class DBItem + { + public: + enum { ResultRequest, ResultGrant, VerifyRequest, VerifyGrant, Validated }; + int type; + Jid to, from; + QString key, id; + bool ok; + }; + + private: + enum Step { + Start, + Done, + SendFeatures, + GetRequest, + HandleTLS, + GetSASLResponse, + IncHandleSASLSuccess, + GetFeatures, // read features packet + HandleFeatures, // act on features, by initiating tls, sasl, or bind + GetTLSProceed, // read <proceed/> tls response + GetSASLFirst, // perform sasl first step using provided data + GetSASLChallenge, // read server sasl challenge + GetSASLNext, // perform sasl next step using provided data + HandleSASLSuccess, // handle what must be done after reporting sasl success + GetBindResponse, // read bind response + HandleAuthGet, // send old-protocol auth-get + GetAuthGetResponse, // read auth-get response + HandleAuthSet, // send old-protocol auth-set + GetAuthSetResponse // read auth-set response + }; + + QValueList<DBItem> dbrequests, dbpending, dbvalidated; + + bool server, dialback, dialback_verify; + int step; + + bool digest; + bool tls_started, sasl_started; + + Jid jid; + bool oldOnly; + bool allowPlain; + bool doTLS, doAuth, doBinding; + QString password; + + QString dialback_id, dialback_key; + QString self_from; + + void init(); + static int getOldErrorCode(const QDomElement &e); + bool loginComplete(); + + bool isValidStanza(const QDomElement &e) const; + bool grabPendingItem(const Jid &to, const Jid &from, int type, DBItem *item); + bool normalStep(const QDomElement &e); + bool dialbackStep(const QDomElement &e); + + // reimplemented + bool stepAdvancesParser() const; + bool stepRequiresElement() const; + void stringSend(const QString &s); + void stringRecv(const QString &s); + QString defaultNamespace(); + QStringList extraNamespaces(); + void handleStreamOpen(const Parser::Event &pe); + bool doStep2(const QDomElement &e); + void elementSend(const QDomElement &e); + void elementRecv(const QDomElement &e); + }; +} + +#endif |