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