You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdenetwork/kopete/protocols/jabber/libiris/iris/xmpp-core/protocol.h

356 lines
9.6 KiB

/*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef PROTOCOL_H
#define PROTOCOL_H
#include <tqpair.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;
TQStringList 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
TQDomDocument doc;
// sasl-related
TQString saslMech() const;
TQByteArray saslStep() const;
void setSASLMechList(const TQStringList &list);
void setSASLFirst(const TQString &mech, const TQByteArray &step);
void setSASLNext(const TQByteArray &step);
void setSASLAuthed();
// send / recv
void sendStanza(const TQDomElement &e);
void sendDirect(const TQString &s);
void sendWhitespace();
TQDomElement recvStanza();
// shutdown
void shutdown();
void shutdownWithError(int cond, const TQString &otherHost="");
// <stream> information
TQString to, from, id, lang;
Version version;
// error output
int errCond;
TQString errText;
TQDomElement errAppSpec;
TQString otherHost;
TQByteArray spare; // filled with unprocessed data on NStartTLS and NSASLLayer
bool isReady() const;
enum { TypeElement, TypeStanza, TypeDirect, TypePing };
protected:
static int stringToSASLCond(const TQString &s);
static int stringToStreamCond(const TQString &s);
static TQString saslCondToString(int);
static TQString streamCondToString(int);
void send(const TQDomElement &e, bool clip=false);
void sendStreamError(int cond, const TQString &text="", const TQDomElement &appSpec=TQDomElement());
void sendStreamError(const TQString &text); // old-style
bool errorAndClose(int cond, const TQString &text="", const TQDomElement &appSpec=TQDomElement());
bool error(int code);
void delayErrorAndClose(int cond, const TQString &text="", const TQDomElement &appSpec=TQDomElement());
void delayError(int code);
// reimplemented
TQDomElement docElement();
void handleDocOpen(const Parser::Event &pe);
bool handleError();
bool handleCloseFinished();
bool doStep(const TQDomElement &e);
void itemWritten(int id, int size);
virtual TQString defaultNamespace();
virtual TQStringList extraNamespaces(); // stringlist: prefix,uri,prefix,uri, [...]
virtual void handleStreamOpen(const Parser::Event &pe);
virtual bool doStep2(const TQDomElement &e)=0;
void setReady(bool b);
TQString sasl_mech;
TQStringList sasl_mechlist;
TQByteArray sasl_step;
bool sasl_authed;
TQDomElement stanzaToRecv;
private:
struct SASLCondEntry
{
const char *str;
int cond;
};
static SASLCondEntry saslCondTable[];
struct StreamCondEntry
{
const char *str;
int cond;
};
static StreamCondEntry streamCondTable[];
struct SendItem
{
TQDomElement stanzaToSend;
TQString stringToSend;
bool doWhitespace;
};
TQValueList<SendItem> sendList;
bool doShutdown, delayedError, closeError, ready;
int stanzasPending, stanzasWritten;
void init();
void extractStreamError(const TQDomElement &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 TQString &to);
void startDialbackOut(const TQString &to, const TQString &from);
void startDialbackVerifyOut(const TQString &to, const TQString &from, const TQString &id, const TQString &key);
void startClientIn(const TQString &id);
void startServerIn(const TQString &id);
void setLang(const TQString &s);
void setAllowTLS(bool b);
void setAllowBind(bool b);
void setAllowPlain(bool b); // old-mode
void setPassword(const TQString &s);
void setFrom(const TQString &s);
void setDialbackKey(const TQString &s);
// input
TQString user, host;
// status
bool old;
StreamFeatures features;
//static TQString xmlToString(const TQDomElement &e, bool clip=false);
class DBItem
{
public:
enum { ResultRequest, ResultGrant, VerifyRequest, VerifyGrant, Validated };
int type;
Jid to, from;
TQString 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
};
TQValueList<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;
TQString password;
TQString dialback_id, dialback_key;
TQString self_from;
void init();
static int getOldErrorCode(const TQDomElement &e);
bool loginComplete();
bool isValidStanza(const TQDomElement &e) const;
bool grabPendingItem(const Jid &to, const Jid &from, int type, DBItem *item);
bool normalStep(const TQDomElement &e);
bool dialbackStep(const TQDomElement &e);
// reimplemented
bool stepAdvancesParser() const;
bool stepRequiresElement() const;
void stringSend(const TQString &s);
void stringRecv(const TQString &s);
TQString defaultNamespace();
TQStringList extraNamespaces();
void handleStreamOpen(const Parser::Event &pe);
bool doStep2(const TQDomElement &e);
void elementSend(const TQDomElement &e);
void elementRecv(const TQDomElement &e);
};
}
#endif