2
* protocol.h - XMPP-Core protocol state machine
3
* Copyright (C) 2004 Justin Karneges
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
#include "xmlprotocol.h"
30
#define NS_ETHERX "http://etherx.jabber.org/streams"
31
#define NS_CLIENT "jabber:client"
32
#define NS_SERVER "jabber:server"
33
#define NS_DIALBACK "jabber:server:dialback"
34
#define NS_STREAMS "urn:ietf:params:xml:ns:xmpp-streams"
35
#define NS_TLS "urn:ietf:params:xml:ns:xmpp-tls"
36
#define NS_SASL "urn:ietf:params:xml:ns:xmpp-sasl"
37
#define NS_SESSION "urn:ietf:params:xml:ns:xmpp-session"
38
#define NS_STANZAS "urn:ietf:params:xml:ns:xmpp-stanzas"
39
#define NS_BIND "urn:ietf:params:xml:ns:xmpp-bind"
40
#define NS_COMPRESS_FEATURE "http://jabber.org/features/compress"
41
#define NS_COMPRESS_PROTOCOL "http://jabber.org/protocol/compress"
48
Version(int maj=0, int min=0);
58
bool tls_supported, sasl_supported, bind_supported, compress_supported;
60
QStringList sasl_mechs;
61
QStringList compression_mechs;
64
class BasicProtocol : public XmlProtocol
67
// xmpp 1.0 error conditions
92
RemoteConnectionFailed,
99
UnsupportedStanzaType,
109
// extend the XmlProtocol enums
111
NSASLMechs = XmlProtocol::NCustom, // need SASL mechlist
112
NStartTLS, // need to switch on TLS layer
113
NCompress, // need to switch on compression layer
114
NSASLFirst, // need SASL first step
115
NSASLNext, // need SASL next step
116
NSASLLayer, // need to switch on SASL layer
117
NCustom = XmlProtocol::NCustom+10
120
EFeatures = XmlProtocol::ECustom, // breakpoint after features packet is received
121
ESASLSuccess, // breakpoint after successful sasl auth
122
EStanzaReady, // a stanza was received
123
EStanzaSent, // a stanza was sent
124
EReady, // stream is ready for stanza use
125
ECustom = XmlProtocol::ECustom+10
128
ErrProtocol = XmlProtocol::ErrCustom, // there was an error in the xmpp-core protocol exchange
129
ErrStream, // <stream:error>, see errCond, errText, and errAppSpec for details
130
ErrStartTLS, // server refused starttls
131
ErrCompress, // server refused compression
132
ErrAuth, // authorization error. errCond holds sasl condition (or numeric code for old-protocol)
133
ErrBind, // server refused resource bind
134
ErrCustom = XmlProtocol::ErrCustom+10
146
QString saslMech() const;
147
QByteArray saslStep() const;
148
void setSASLMechList(const QStringList &list);
149
void setSASLFirst(const QString &mech, const QByteArray &step);
150
void setSASLNext(const QByteArray &step);
151
void setSASLAuthed();
154
void sendStanza(const QDomElement &e);
155
void sendDirect(const QString &s);
156
void sendWhitespace();
157
QDomElement recvStanza();
161
void shutdownWithError(int cond, const QString &otherHost="");
163
// <stream> information
164
QString to, from, id, lang;
170
QDomElement errAppSpec;
173
QByteArray spare; // filled with unprocessed data on NStartTLS and NSASLLayer
175
bool isReady() const;
177
enum { TypeElement, TypeStanza, TypeDirect, TypePing };
180
static int stringToSASLCond(const QString &s);
181
static int stringToStreamCond(const QString &s);
182
static QString saslCondToString(int);
183
static QString streamCondToString(int);
185
void send(const QDomElement &e, bool clip=false);
186
void sendStreamError(int cond, const QString &text="", const QDomElement &appSpec=QDomElement());
187
void sendStreamError(const QString &text); // old-style
189
bool errorAndClose(int cond, const QString &text="", const QDomElement &appSpec=QDomElement());
190
bool error(int code);
191
void delayErrorAndClose(int cond, const QString &text="", const QDomElement &appSpec=QDomElement());
192
void delayError(int code);
195
QDomElement docElement();
196
void handleDocOpen(const Parser::Event &pe);
198
bool handleCloseFinished();
199
bool doStep(const QDomElement &e);
200
void itemWritten(int id, int size);
202
virtual QString defaultNamespace();
203
virtual QStringList extraNamespaces(); // stringlist: prefix,uri,prefix,uri, [...]
204
virtual void handleStreamOpen(const Parser::Event &pe);
205
virtual bool doStep2(const QDomElement &e)=0;
207
void setReady(bool b);
210
QStringList sasl_mechlist;
211
QByteArray sasl_step;
214
QDomElement stanzaToRecv;
222
static SASLCondEntry saslCondTable[];
224
struct StreamCondEntry
229
static StreamCondEntry streamCondTable[];
233
QDomElement stanzaToSend;
234
QString stringToSend;
237
QList<SendItem> sendList;
239
bool doShutdown, delayedError, closeError, ready;
240
int stanzasPending, stanzasWritten;
243
void extractStreamError(const QDomElement &e);
246
class CoreProtocol : public BasicProtocol
250
NPassword = NCustom, // need password for old-mode
251
EDBVerify = ECustom, // breakpoint after db:verify request
252
ErrPlain = ErrCustom // server only supports plain, but allowPlain is false locally
260
void startClientOut(const Jid &jid, bool oldOnly, bool tlsActive, bool doAuth, bool doCompression);
261
void startServerOut(const QString &to);
262
void startDialbackOut(const QString &to, const QString &from);
263
void startDialbackVerifyOut(const QString &to, const QString &from, const QString &id, const QString &key);
264
void startClientIn(const QString &id);
265
void startServerIn(const QString &id);
267
void setLang(const QString &s);
268
void setAllowTLS(bool b);
269
void setAllowBind(bool b);
270
void setAllowPlain(bool b); // old-mode
271
const Jid& jid() const;
273
void setPassword(const QString &s);
274
void setFrom(const QString &s);
275
void setDialbackKey(const QString &s);
283
StreamFeatures features;
285
//static QString xmlToString(const QDomElement &e, bool clip=false);
290
enum { ResultRequest, ResultGrant, VerifyRequest, VerifyGrant, Validated };
305
IncHandleSASLSuccess,
306
GetFeatures, // read features packet
307
HandleFeatures, // act on features, by initiating tls, sasl, or bind
308
GetTLSProceed, // read <proceed/> tls response
309
GetCompressProceed, // read <compressed/> compression response
310
GetSASLFirst, // perform sasl first step using provided data
311
GetSASLChallenge, // read server sasl challenge
312
GetSASLNext, // perform sasl next step using provided data
313
HandleSASLSuccess, // handle what must be done after reporting sasl success
314
GetBindResponse, // read bind response
315
HandleAuthGet, // send old-protocol auth-get
316
GetAuthGetResponse, // read auth-get response
317
HandleAuthSet, // send old-protocol auth-set
318
GetAuthSetResponse // read auth-set response
321
QList<DBItem> dbrequests, dbpending, dbvalidated;
323
bool server, dialback, dialback_verify;
327
bool tls_started, sasl_started, compress_started;
332
bool doTLS, doAuth, doBinding, doCompress;
335
QString dialback_id, dialback_key;
339
static int getOldErrorCode(const QDomElement &e);
340
bool loginComplete();
342
bool isValidStanza(const QDomElement &e) const;
343
bool grabPendingItem(const Jid &to, const Jid &from, int type, DBItem *item);
344
bool normalStep(const QDomElement &e);
345
bool dialbackStep(const QDomElement &e);
348
bool stepAdvancesParser() const;
349
bool stepRequiresElement() const;
350
void stringSend(const QString &s);
351
void stringRecv(const QString &s);
352
QString defaultNamespace();
353
QStringList extraNamespaces();
354
void handleStreamOpen(const Parser::Event &pe);
355
bool doStep2(const QDomElement &e);
356
void elementSend(const QDomElement &e);
357
void elementRecv(const QDomElement &e);