1 /* 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_XMPPENGINE_H_ 12 #define WEBRTC_LIBJINGLE_XMPP_XMPPENGINE_H_ 13 14 // also part of the API 15 #include "webrtc/libjingle/xmllite/qname.h" 16 #include "webrtc/libjingle/xmllite/xmlelement.h" 17 #include "webrtc/libjingle/xmpp/jid.h" 18 19 20 namespace buzz { 21 22 class XmppEngine; 23 class SaslHandler; 24 typedef void * XmppIqCookie; 25 26 //! XMPP stanza error codes. 27 //! Used in XmppEngine.SendStanzaError(). 28 enum XmppStanzaError { 29 XSE_BAD_REQUEST, 30 XSE_CONFLICT, 31 XSE_FEATURE_NOT_IMPLEMENTED, 32 XSE_FORBIDDEN, 33 XSE_GONE, 34 XSE_INTERNAL_SERVER_ERROR, 35 XSE_ITEM_NOT_FOUND, 36 XSE_JID_MALFORMED, 37 XSE_NOT_ACCEPTABLE, 38 XSE_NOT_ALLOWED, 39 XSE_PAYMENT_REQUIRED, 40 XSE_RECIPIENT_UNAVAILABLE, 41 XSE_REDIRECT, 42 XSE_REGISTRATION_REQUIRED, 43 XSE_SERVER_NOT_FOUND, 44 XSE_SERVER_TIMEOUT, 45 XSE_RESOURCE_CONSTRAINT, 46 XSE_SERVICE_UNAVAILABLE, 47 XSE_SUBSCRIPTION_REQUIRED, 48 XSE_UNDEFINED_CONDITION, 49 XSE_UNEXPECTED_REQUEST, 50 }; 51 52 // XmppReturnStatus 53 // This is used by API functions to synchronously return status. 54 enum XmppReturnStatus { 55 XMPP_RETURN_OK, 56 XMPP_RETURN_BADARGUMENT, 57 XMPP_RETURN_BADSTATE, 58 XMPP_RETURN_PENDING, 59 XMPP_RETURN_UNEXPECTED, 60 XMPP_RETURN_NOTYETIMPLEMENTED, 61 }; 62 63 // TlsOptions 64 // This is used by API to identify TLS setting. 65 enum TlsOptions { 66 TLS_DISABLED, 67 TLS_ENABLED, 68 TLS_REQUIRED 69 }; 70 71 //! Callback for socket output for an XmppEngine connection. 72 //! Register via XmppEngine.SetOutputHandler. An XmppEngine 73 //! can call back to this handler while it is processing 74 //! Connect, SendStanza, SendIq, Disconnect, or HandleInput. 75 class XmppOutputHandler { 76 public: 77 virtual ~XmppOutputHandler() {} 78 79 //! Deliver the specified bytes to the XMPP socket. 80 virtual void WriteOutput(const char * bytes, size_t len) = 0; 81 82 //! Initiate TLS encryption on the socket. 83 //! The implementation must verify that the SSL 84 //! certificate matches the given domainname. 85 virtual void StartTls(const std::string & domainname) = 0; 86 87 //! Called when engine wants the connecton closed. 88 virtual void CloseConnection() = 0; 89 }; 90 91 //! Callback to deliver engine state change notifications 92 //! to the object managing the engine. 93 class XmppSessionHandler { 94 public: 95 virtual ~XmppSessionHandler() {} 96 //! Called when engine changes state. Argument is new state. 97 virtual void OnStateChange(int state) = 0; 98 }; 99 100 //! Callback to deliver stanzas to an Xmpp application module. 101 //! Register via XmppEngine.SetDefaultSessionHandler or via 102 //! XmppEngine.AddSessionHAndler. 103 class XmppStanzaHandler { 104 public: 105 virtual ~XmppStanzaHandler() {} 106 //! Process the given stanza. 107 //! The handler must return true if it has handled the stanza. 108 //! A false return value causes the stanza to be passed on to 109 //! the next registered handler. 110 virtual bool HandleStanza(const XmlElement * stanza) = 0; 111 }; 112 113 //! Callback to deliver iq responses (results and errors). 114 //! Register while sending an iq via XmppEngine.SendIq. 115 //! Iq responses are routed to matching XmppIqHandlers in preference 116 //! to sending to any registered SessionHandlers. 117 class XmppIqHandler { 118 public: 119 virtual ~XmppIqHandler() {} 120 //! Called to handle the iq response. 121 //! The response may be either a result or an error, and will have 122 //! an 'id' that matches the request and a 'from' that matches the 123 //! 'to' of the request. Called no more than once; once this is 124 //! called, the handler is automatically unregistered. 125 virtual void IqResponse(XmppIqCookie cookie, const XmlElement * pelStanza) = 0; 126 }; 127 128 //! The XMPP connection engine. 129 //! This engine implements the client side of the 'core' XMPP protocol. 130 //! To use it, register an XmppOutputHandler to handle socket output 131 //! and pass socket input to HandleInput. Then application code can 132 //! set up the connection with a user, password, and other settings, 133 //! and then call Connect() to initiate the connection. 134 //! An application can listen for events and receive stanzas by 135 //! registering an XmppStanzaHandler via AddStanzaHandler(). 136 class XmppEngine { 137 public: 138 static XmppEngine * Create(); 139 virtual ~XmppEngine() {} 140 141 //! Error codes. See GetError(). 142 enum Error { 143 ERROR_NONE = 0, //!< No error 144 ERROR_XML, //!< Malformed XML or encoding error 145 ERROR_STREAM, //!< XMPP stream error - see GetStreamError() 146 ERROR_VERSION, //!< XMPP version error 147 ERROR_UNAUTHORIZED, //!< User is not authorized (rejected credentials) 148 ERROR_TLS, //!< TLS could not be negotiated 149 ERROR_AUTH, //!< Authentication could not be negotiated 150 ERROR_BIND, //!< Resource or session binding could not be negotiated 151 ERROR_CONNECTION_CLOSED,//!< Connection closed by output handler. 152 ERROR_DOCUMENT_CLOSED, //!< Closed by </stream:stream> 153 ERROR_SOCKET, //!< Socket error 154 ERROR_NETWORK_TIMEOUT, //!< Some sort of timeout (eg., we never got the roster) 155 ERROR_MISSING_USERNAME //!< User has a Google Account but no nickname 156 }; 157 158 //! States. See GetState(). 159 enum State { 160 STATE_NONE = 0, //!< Nonexistent state 161 STATE_START, //!< Initial state. 162 STATE_OPENING, //!< Exchanging stream headers, authenticating and so on. 163 STATE_OPEN, //!< Authenticated and bound. 164 STATE_CLOSED, //!< Session closed, possibly due to error. 165 }; 166 167 // SOCKET INPUT AND OUTPUT ------------------------------------------------ 168 169 //! Registers the handler for socket output 170 virtual XmppReturnStatus SetOutputHandler(XmppOutputHandler *pxoh) = 0; 171 172 //! Provides socket input to the engine 173 virtual XmppReturnStatus HandleInput(const char * bytes, size_t len) = 0; 174 175 //! Advises the engine that the socket has closed 176 virtual XmppReturnStatus ConnectionClosed(int subcode) = 0; 177 178 // SESSION SETUP --------------------------------------------------------- 179 180 //! Indicates the (bare) JID for the user to use. 181 virtual XmppReturnStatus SetUser(const Jid & jid)= 0; 182 183 //! Get the login (bare) JID. 184 virtual const Jid & GetUser() = 0; 185 186 //! Provides different methods for credentials for login. 187 //! Takes ownership of this object; deletes when login is done 188 virtual XmppReturnStatus SetSaslHandler(SaslHandler * h) = 0; 189 190 //! Sets whether TLS will be used within the connection (default true). 191 virtual XmppReturnStatus SetTls(TlsOptions useTls) = 0; 192 193 //! Sets an alternate domain from which we allows TLS certificates. 194 //! This is for use in the case where a we want to allow a proxy to 195 //! serve up its own certificate rather than one owned by the underlying 196 //! domain. 197 virtual XmppReturnStatus SetTlsServer(const std::string & proxy_hostname, 198 const std::string & proxy_domain) = 0; 199 200 //! Gets whether TLS will be used within the connection. 201 virtual TlsOptions GetTls() = 0; 202 203 //! Sets the request resource name, if any (optional). 204 //! Note that the resource name may be overridden by the server; after 205 //! binding, the actual resource name is available as part of FullJid(). 206 virtual XmppReturnStatus SetRequestedResource(const std::string& resource) = 0; 207 208 //! Gets the request resource name. 209 virtual const std::string & GetRequestedResource() = 0; 210 211 //! Sets language 212 virtual void SetLanguage(const std::string & lang) = 0; 213 214 // SESSION MANAGEMENT --------------------------------------------------- 215 216 //! Set callback for state changes. 217 virtual XmppReturnStatus SetSessionHandler(XmppSessionHandler* handler) = 0; 218 219 //! Initiates the XMPP connection. 220 //! After supplying connection settings, call this once to initiate, 221 //! (optionally) encrypt, authenticate, and bind the connection. 222 virtual XmppReturnStatus Connect() = 0; 223 224 //! The current engine state. 225 virtual State GetState() = 0; 226 227 //! Returns true if the connection is encrypted (under TLS) 228 virtual bool IsEncrypted() = 0; 229 230 //! The error code. 231 //! Consult this after XmppOutputHandler.OnClose(). 232 virtual Error GetError(int *subcode) = 0; 233 234 //! The stream:error stanza, when the error is XmppEngine::ERROR_STREAM. 235 //! Notice the stanza returned is owned by the XmppEngine and 236 //! is deleted when the engine is destroyed. 237 virtual const XmlElement * GetStreamError() = 0; 238 239 //! Closes down the connection. 240 //! Sends CloseConnection to output, and disconnects and registered 241 //! session handlers. After Disconnect completes, it is guaranteed 242 //! that no further callbacks will be made. 243 virtual XmppReturnStatus Disconnect() = 0; 244 245 // APPLICATION USE ------------------------------------------------------- 246 247 enum HandlerLevel { 248 HL_NONE = 0, 249 HL_PEEK, //!< Sees messages before all other processing; cannot abort 250 HL_SINGLE, //!< Watches for a single message, e.g., by id and sender 251 HL_SENDER, //!< Watches for a type of message from a specific sender 252 HL_TYPE, //!< Watches a type of message, e.g., all groupchat msgs 253 HL_ALL, //!< Watches all messages - gets last shot 254 HL_COUNT, //!< Count of handler levels 255 }; 256 257 //! Adds a listener for session events. 258 //! Stanza delivery is chained to session handlers; the first to 259 //! return 'true' is the last to get each stanza. 260 virtual XmppReturnStatus AddStanzaHandler(XmppStanzaHandler* handler, HandlerLevel level = HL_PEEK) = 0; 261 262 //! Removes a listener for session events. 263 virtual XmppReturnStatus RemoveStanzaHandler(XmppStanzaHandler* handler) = 0; 264 265 //! Sends a stanza to the server. 266 virtual XmppReturnStatus SendStanza(const XmlElement * pelStanza) = 0; 267 268 //! Sends raw text to the server 269 virtual XmppReturnStatus SendRaw(const std::string & text) = 0; 270 271 //! Sends an iq to the server, and registers a callback for the result. 272 //! Returns the cookie passed to the result handler. 273 virtual XmppReturnStatus SendIq(const XmlElement* pelStanza, 274 XmppIqHandler* iq_handler, 275 XmppIqCookie* cookie) = 0; 276 277 //! Unregisters an iq callback handler given its cookie. 278 //! No callback will come to this handler after it's unregistered. 279 virtual XmppReturnStatus RemoveIqHandler(XmppIqCookie cookie, 280 XmppIqHandler** iq_handler) = 0; 281 282 283 //! Forms and sends an error in response to the given stanza. 284 //! Swaps to and from, sets type to "error", and adds error information 285 //! based on the passed code. Text is optional and may be STR_EMPTY. 286 virtual XmppReturnStatus SendStanzaError(const XmlElement * pelOriginal, 287 XmppStanzaError code, 288 const std::string & text) = 0; 289 290 //! The fullly bound JID. 291 //! This JID is only valid after binding has succeeded. If the value 292 //! is JID_NULL, the binding has not succeeded. 293 virtual const Jid & FullJid() = 0; 294 295 //! The next unused iq id for this connection. 296 //! Call this when building iq stanzas, to ensure that each iq 297 //! gets its own unique id. 298 virtual std::string NextId() = 0; 299 300 }; 301 302 } 303 304 305 // Move these to a better location 306 307 #define XMPP_FAILED(x) \ 308 ( (x) == buzz::XMPP_RETURN_OK ? false : true) \ 309 310 311 #define XMPP_SUCCEEDED(x) \ 312 ( (x) == buzz::XMPP_RETURN_OK ? true : false) \ 313 314 #define IFR(x) \ 315 do { \ 316 xmpp_status = (x); \ 317 if (XMPP_FAILED(xmpp_status)) { \ 318 return xmpp_status; \ 319 } \ 320 } while (false) \ 321 322 323 #define IFC(x) \ 324 do { \ 325 xmpp_status = (x); \ 326 if (XMPP_FAILED(xmpp_status)) { \ 327 goto Cleanup; \ 328 } \ 329 } while (false) \ 330 331 332 #endif // WEBRTC_LIBJINGLE_XMPP_XMPPENGINE_H_ 333