1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
|
/*
* libjingle
* Copyright 2004--2005, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _xmppengineimpl_h_
#define _xmppengineimpl_h_
#include <sstream>
#include "talk/xmpp/xmppengine.h"
#include "talk/xmpp/xmppstanzaparser.h"
namespace buzz {
class XmppLoginTask;
class XmppEngine;
class XmppIqEntry;
class SaslHandler;
class SaslMechanism;
//! The XMPP connection engine.
//! This engine implements the client side of the 'core' XMPP protocol.
//! To use it, register an XmppOutputHandler to handle socket output
//! and pass socket input to HandleInput. Then application code can
//! set up the connection with a user, password, and other settings,
//! and then call Connect() to initiate the connection.
//! An application can listen for events and receive stanzas by
//! registering an XmppStanzaHandler via AddStanzaHandler().
class XmppEngineImpl : public XmppEngine {
public:
XmppEngineImpl();
virtual ~XmppEngineImpl();
// SOCKET INPUT AND OUTPUT ------------------------------------------------
//! Registers the handler for socket output
virtual XmppReturnStatus SetOutputHandler(XmppOutputHandler *pxoh);
//! Provides socket input to the engine
virtual XmppReturnStatus HandleInput(const char * bytes, size_t len);
//! Advises the engine that the socket has closed
virtual XmppReturnStatus ConnectionClosed();
// SESSION SETUP ---------------------------------------------------------
//! Indicates the (bare) JID for the user to use.
virtual XmppReturnStatus SetUser(const Jid & jid);
//! Get the login (bare) JID.
virtual const Jid & GetUser();
//! Indicates the autentication to use. Takes ownership of the object.
virtual XmppReturnStatus SetSaslHandler(SaslHandler * sasl_handler);
//! Sets whether TLS will be used within the connection (default true).
virtual XmppReturnStatus SetUseTls(bool useTls);
//! Sets an alternate domain from which we allows TLS certificates.
//! This is for use in the case where a we want to allow a proxy to
//! serve up its own certificate rather than one owned by the underlying
//! domain.
virtual XmppReturnStatus SetTlsServerDomain(const std::string & proxy_domain);
//! Gets whether TLS will be used within the connection.
virtual bool GetUseTls();
//! Sets the request resource name, if any (optional).
//! Note that the resource name may be overridden by the server; after
//! binding, the actual resource name is available as part of FullJid().
virtual XmppReturnStatus SetRequestedResource(const std::string& resource);
//! Gets the request resource name.
virtual const std::string & GetRequestedResource();
// SESSION MANAGEMENT ---------------------------------------------------
//! Set callback for state changes.
virtual XmppReturnStatus SetSessionHandler(XmppSessionHandler* handler);
//! Initiates the XMPP connection.
//! After supplying connection settings, call this once to initiate,
//! (optionally) encrypt, authenticate, and bind the connection.
virtual XmppReturnStatus Connect();
//! The current engine state.
virtual State GetState() { return state_; }
//! Returns true if the connection is encrypted (under TLS)
virtual bool IsEncrypted() { return encrypted_; }
//! The error code.
//! Consult this after XmppOutputHandler.OnClose().
virtual Error GetError() { return error_code_; }
//! The stream:error stanza, when the error is XMPP_ERROR_STREAM.
//! Notice the stanza returned is owned by the XmppEngine and
//! is deleted when the engine is destroyed.
virtual const XmlElement * GetStreamError() { return stream_error_.get(); }
//! Closes down the connection.
//! Sends CloseConnection to output, and disconnects and registered
//! session handlers. After Disconnect completes, it is guaranteed
//! that no further callbacks will be made.
virtual XmppReturnStatus Disconnect();
// APPLICATION USE -------------------------------------------------------
//! Adds a listener for session events.
//! Stanza delivery is chained to session handlers; the first to
//! return 'true' is the last to get each stanza.
virtual XmppReturnStatus AddStanzaHandler(XmppStanzaHandler* handler,
XmppEngine::HandlerLevel level);
//! Removes a listener for session events.
virtual XmppReturnStatus RemoveStanzaHandler(XmppStanzaHandler* handler);
//! Sends a stanza to the server.
virtual XmppReturnStatus SendStanza(const XmlElement * pelStanza);
//! Sends raw text to the server
virtual XmppReturnStatus SendRaw(const std::string & text);
//! Sends an iq to the server, and registers a callback for the result.
//! Returns the cookie passed to the result handler.
virtual XmppReturnStatus SendIq(const XmlElement* pelStanza,
XmppIqHandler* iq_handler,
XmppIqCookie* cookie);
//! Unregisters an iq callback handler given its cookie.
//! No callback will come to this handler after it's unregistered.
virtual XmppReturnStatus RemoveIqHandler(XmppIqCookie cookie,
XmppIqHandler** iq_handler);
//! Forms and sends an error in response to the given stanza.
//! Swaps to and from, sets type to "error", and adds error information
//! based on the passed code. Text is optional and may be STR_EMPTY.
virtual XmppReturnStatus SendStanzaError(const XmlElement * pelOriginal,
XmppStanzaError code,
const std::string & text);
//! The fullly bound JID.
//! This JID is only valid after binding has succeeded. If the value
//! is JID_NULL, the binding has not succeeded.
virtual const Jid & FullJid() { return bound_jid_; }
//! The next unused iq id for this connection.
//! Call this when building iq stanzas, to ensure that each iq
//! gets its own unique id.
virtual std::string NextId();
private:
friend class XmppLoginTask;
friend class XmppIqEntry;
void IncomingStanza(const XmlElement *pelStanza);
void IncomingStart(const XmlElement *pelStanza);
void IncomingEnd(bool isError);
void InternalSendStart(const std::string & domainName);
void InternalSendStanza(const XmlElement * pelStanza);
std::string ChooseBestSaslMechanism(const std::vector<std::string> & mechanisms, bool encrypted);
SaslMechanism * GetSaslMechanism(const std::string & name);
void SignalBound(const Jid & fullJid);
void SignalStreamError(const XmlElement * pelStreamError);
void SignalError(Error errorCode);
bool HasError();
void DeleteIqCookies();
bool HandleIqResponse(const XmlElement * element);
void StartTls(const std::string & domain);
void RaiseReset() { raised_reset_ = true; }
class StanzaParseHandler : public XmppStanzaParseHandler {
public:
StanzaParseHandler(XmppEngineImpl * outer) : outer_(outer) {}
virtual void StartStream(const XmlElement * pelStream)
{ outer_->IncomingStart(pelStream); }
virtual void Stanza(const XmlElement * pelStanza)
{ outer_->IncomingStanza(pelStanza); }
virtual void EndStream()
{ outer_->IncomingEnd(false); }
virtual void XmlError()
{ outer_->IncomingEnd(true); }
private:
XmppEngineImpl * const outer_;
};
class EnterExit {
public:
EnterExit(XmppEngineImpl* engine);
~EnterExit();
private:
XmppEngineImpl* engine_;
State state_;
Error error_;
};
friend class StanzaParseHandler;
friend class EnterExit;
StanzaParseHandler stanzaParseHandler_;
XmppStanzaParser stanzaParser_;
// state
int engine_entered_;
Jid user_jid_;
std::string password_;
std::string requested_resource_;
bool tls_needed_;
std::string tls_server_domain_;
scoped_ptr<XmppLoginTask> login_task_;
int next_id_;
Jid bound_jid_;
State state_;
bool encrypted_;
Error error_code_;
scoped_ptr<XmlElement> stream_error_;
bool raised_reset_;
XmppOutputHandler* output_handler_;
XmppSessionHandler* session_handler_;
typedef STD_VECTOR(XmppStanzaHandler*) StanzaHandlerVector;
scoped_ptr<StanzaHandlerVector> stanza_handlers_[HL_COUNT];
typedef STD_VECTOR(XmppIqEntry*) IqEntryVector;
scoped_ptr<IqEntryVector> iq_entries_;
scoped_ptr<SaslHandler> sasl_handler_;
scoped_ptr<std::stringstream> output_;
};
}
#endif
|