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