PageRenderTime 46ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/XMPP_Demo/Core/XMPPStream.h

https://gitlab.com/praveenvelanati/ios-demo
C Header | 901 lines | 138 code | 89 blank | 674 comment | 0 complexity | eca88db01da3de1be6bf3b50a8ba4185 MD5 | raw file
  1. #import <Foundation/Foundation.h>
  2. #import "XMPPSASLAuthentication.h"
  3. #import "GCDAsyncSocket.h"
  4. #import "GCDMulticastDelegate.h"
  5. #if TARGET_OS_IPHONE
  6. #import "DDXML.h"
  7. #endif
  8. @class XMPPSRVResolver;
  9. @class XMPPParser;
  10. @class XMPPJID;
  11. @class XMPPIQ;
  12. @class XMPPMessage;
  13. @class XMPPPresence;
  14. @class XMPPModule;
  15. @class XMPPElementReceipt;
  16. @protocol XMPPStreamDelegate;
  17. #if TARGET_OS_IPHONE
  18. #define MIN_KEEPALIVE_INTERVAL 20.0 // 20 Seconds
  19. #define DEFAULT_KEEPALIVE_INTERVAL 120.0 // 2 Minutes
  20. #else
  21. #define MIN_KEEPALIVE_INTERVAL 10.0 // 10 Seconds
  22. #define DEFAULT_KEEPALIVE_INTERVAL 300.0 // 5 Minutes
  23. #endif
  24. extern NSString *const XMPPStreamErrorDomain;
  25. enum XMPPStreamErrorCode
  26. {
  27. XMPPStreamInvalidType, // Attempting to access P2P methods in a non-P2P stream, or vice-versa
  28. XMPPStreamInvalidState, // Invalid state for requested action, such as connect when already connected
  29. XMPPStreamInvalidProperty, // Missing a required property, such as myJID
  30. XMPPStreamInvalidParameter, // Invalid parameter, such as a nil JID
  31. XMPPStreamUnsupportedAction, // The server doesn't support the requested action
  32. };
  33. typedef enum XMPPStreamErrorCode XMPPStreamErrorCode;
  34. @interface XMPPStream : NSObject <GCDAsyncSocketDelegate>
  35. /**
  36. * Standard XMPP initialization.
  37. * The stream is a standard client to server connection.
  38. *
  39. * P2P streams using XEP-0174 are also supported.
  40. * See the P2P section below.
  41. **/
  42. - (id)init;
  43. /**
  44. * Peer to Peer XMPP initialization.
  45. * The stream is a direct client to client connection as outlined in XEP-0174.
  46. **/
  47. - (id)initP2PFrom:(XMPPJID *)myJID;
  48. /**
  49. * XMPPStream uses a multicast delegate.
  50. * This allows one to add multiple delegates to a single XMPPStream instance,
  51. * which makes it easier to separate various components and extensions.
  52. *
  53. * For example, if you were implementing two different custom extensions on top of XMPP,
  54. * you could put them in separate classes, and simply add each as a delegate.
  55. **/
  56. - (void)addDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue;
  57. - (void)removeDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue;
  58. - (void)removeDelegate:(id)delegate;
  59. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  60. #pragma mark Properties
  61. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  62. /**
  63. * The server's hostname that should be used to make the TCP connection.
  64. * This may be a domain name (e.g. "deusty.com") or an IP address (e.g. "70.85.193.226").
  65. *
  66. * Note that this may be different from the virtual xmpp hostname.
  67. * Just as HTTP servers can support mulitple virtual hosts from a single server, so too can xmpp servers.
  68. * A prime example is google via google apps.
  69. *
  70. * For example, say you own the domain "mydomain.com".
  71. * If you go to mydomain.com in a web browser,
  72. * you are directed to your apache server running on your webserver somewhere in the cloud.
  73. * But you use google apps for your email and xmpp needs.
  74. * So if somebody sends you an email, it actually goes to google's servers, where you later access it from.
  75. * Similarly, you connect to google's servers to sign into xmpp.
  76. *
  77. * In the example above, your hostname is "talk.google.com" and your JID is "me@mydomain.com".
  78. *
  79. * This hostName property is optional.
  80. * If you do not set the hostName, then the framework will follow the xmpp specification using jid's domain.
  81. * That is, it first do an SRV lookup (as specified in the xmpp RFC).
  82. * If that fails, it will fall back to simply attempting to connect to the jid's domain.
  83. **/
  84. @property (readwrite, copy) NSString *hostName;
  85. /**
  86. * The port the xmpp server is running on.
  87. * If you do not explicitly set the port, the default port will be used.
  88. * If you set the port to zero, the default port will be used.
  89. *
  90. * The default port is 5222.
  91. **/
  92. @property (readwrite, assign) UInt16 hostPort;
  93. /**
  94. * The JID of the user.
  95. *
  96. * This value is required, and is used in many parts of the underlying implementation.
  97. * When connecting, the domain of the JID is used to properly specify the correct xmpp virtual host.
  98. * It is used during registration to supply the username of the user to create an account for.
  99. * It is used during authentication to supply the username of the user to authenticate with.
  100. * And the resource may be used post-authentication during the required xmpp resource binding step.
  101. *
  102. * A proper JID is of the form user@domain/resource.
  103. * For example: robbiehanson@deusty.com/work
  104. *
  105. * The resource is optional, in the sense that if one is not supplied,
  106. * one will be automatically generated for you (either by us or by the server).
  107. *
  108. * Please note:
  109. * Resource collisions are handled in different ways depending on server configuration.
  110. *
  111. * For example:
  112. * You are signed in with user1@domain.com/home on your desktop.
  113. * Then you attempt to sign in with user1@domain.com/home on your laptop.
  114. *
  115. * The server could possibly:
  116. * - Reject the resource request for the laptop.
  117. * - Accept the resource request for the laptop, and immediately disconnect the desktop.
  118. * - Automatically assign the laptop another resource without a conflict.
  119. *
  120. * For this reason, you may wish to check the myJID variable after the stream has been connected,
  121. * just in case the resource was changed by the server.
  122. **/
  123. @property (readwrite, copy) XMPPJID *myJID;
  124. /**
  125. * Only used in P2P streams.
  126. **/
  127. @property (strong, readonly) XMPPJID *remoteJID;
  128. /**
  129. * Many routers will teardown a socket mapping if there is no activity on the socket.
  130. * For this reason, the xmpp stream supports sending keep-alive data.
  131. * This is simply whitespace, which is ignored by the xmpp protocol.
  132. *
  133. * Keep-alive data is only sent in the absence of any other data being sent/received.
  134. *
  135. * The default value is defined in DEFAULT_KEEPALIVE_INTERVAL.
  136. * The minimum value is defined in MIN_KEEPALIVE_INTERVAL.
  137. *
  138. * To disable keep-alive, set the interval to zero (or any non-positive number).
  139. *
  140. * The keep-alive timer (if enabled) fires every (keepAliveInterval / 4) seconds.
  141. * Upon firing it checks when data was last sent/received,
  142. * and sends keep-alive data if the elapsed time has exceeded the keepAliveInterval.
  143. * Thus the effective resolution of the keepalive timer is based on the interval.
  144. *
  145. * @see keepAliveWhitespaceCharacter
  146. **/
  147. @property (readwrite, assign) NSTimeInterval keepAliveInterval;
  148. /**
  149. * The keep-alive mechanism sends whitespace which is ignored by the xmpp protocol.
  150. * The default whitespace character is a space (' ').
  151. *
  152. * This can be changed, for whatever reason, to another whitespace character.
  153. * Valid whitespace characters are space(' '), tab('\t') and newline('\n').
  154. *
  155. * If you attempt to set the character to any non-whitespace character, the attempt is ignored.
  156. *
  157. * @see keepAliveInterval
  158. **/
  159. @property (readwrite, assign) char keepAliveWhitespaceCharacter;
  160. /**
  161. * Represents the last sent presence element concerning the presence of myJID on the server.
  162. * In other words, it represents the presence as others see us.
  163. *
  164. * This excludes presence elements sent concerning subscriptions, MUC rooms, etc.
  165. *
  166. * @see resendMyPresence
  167. **/
  168. @property (strong, readonly) XMPPPresence *myPresence;
  169. /**
  170. * Returns the total number of bytes bytes sent/received by the xmpp stream.
  171. *
  172. * By default this is the byte count since the xmpp stream object has been created.
  173. * If the stream has connected/disconnected/reconnected multiple times,
  174. * the count will be the summation of all connections.
  175. *
  176. * The functionality may optionaly be changed to count only the current socket connection.
  177. * See the resetByteCountPerConnection property.
  178. **/
  179. @property (readonly) UInt64 numberOfBytesSent;
  180. @property (readonly) UInt64 numberOfBytesReceived;
  181. /**
  182. * Affects the funtionality of the byte counter.
  183. *
  184. * The default value is NO.
  185. *
  186. * If set to YES, the byte count will be reset just prior to a new connection (in the connect methods).
  187. **/
  188. @property (readwrite, assign) BOOL resetByteCountPerConnection;
  189. /**
  190. * The tag property allows you to associate user defined information with the stream.
  191. * Tag values are not used internally, and should not be used by xmpp modules.
  192. **/
  193. @property (readwrite, strong) id tag;
  194. #if TARGET_OS_IPHONE
  195. /**
  196. * If set, the kCFStreamNetworkServiceTypeVoIP flags will be set on the underlying CFRead/Write streams.
  197. *
  198. * The default value is NO.
  199. **/
  200. @property (readwrite, assign) BOOL enableBackgroundingOnSocket;
  201. #endif
  202. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  203. #pragma mark State
  204. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  205. /**
  206. * Returns YES if the connection is closed, and thus no stream is open.
  207. * If the stream is neither disconnected, nor connected, then a connection is currently being established.
  208. **/
  209. - (BOOL)isDisconnected;
  210. /**
  211. * Returns YES if the connection is open, and the stream has been properly established.
  212. * If the stream is neither disconnected, nor connected, then a connection is currently being established.
  213. *
  214. * If this method returns YES, then it is ready for you to start sending and receiving elements.
  215. **/
  216. - (BOOL)isConnected;
  217. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  218. #pragma mark Connect & Disconnect
  219. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  220. /**
  221. * Connects to the configured hostName on the configured hostPort.
  222. * If the hostName or myJID are not set, this method will return NO and set the error parameter.
  223. **/
  224. - (BOOL)connect:(NSError **)errPtr;
  225. /**
  226. * THIS IS DEPRECATED BY THE XMPP SPECIFICATION.
  227. *
  228. * The xmpp specification outlines the proper use of SSL/TLS by negotiating
  229. * the startTLS upgrade within the stream negotiation.
  230. * This method exists for those ancient servers that still require the connection to be secured prematurely.
  231. *
  232. * Note: Such servers generally use port 5223 for this, which you will need to set.
  233. **/
  234. - (BOOL)oldSchoolSecureConnect:(NSError **)errPtr;
  235. /**
  236. * Starts a P2P connection to the given user and given address.
  237. * This method only works with XMPPStream objects created using the initP2P method.
  238. *
  239. * The given address is specified as a sockaddr structure wrapped in a NSData object.
  240. * For example, a NSData object returned from NSNetservice's addresses method.
  241. **/
  242. - (BOOL)connectTo:(XMPPJID *)remoteJID withAddress:(NSData *)remoteAddr error:(NSError **)errPtr;
  243. /**
  244. * Starts a P2P connection with the given accepted socket.
  245. * This method only works with XMPPStream objects created using the initP2P method.
  246. *
  247. * The given socket should be a socket that has already been accepted.
  248. * The remoteJID will be extracted from the opening stream negotiation.
  249. **/
  250. - (BOOL)connectP2PWithSocket:(GCDAsyncSocket *)acceptedSocket error:(NSError **)errPtr;
  251. /**
  252. * Disconnects from the remote host by closing the underlying TCP socket connection.
  253. * The terminating </stream:stream> element is not sent to the server.
  254. *
  255. * This method is synchronous.
  256. * Meaning that the disconnect will happen immediately, even if there are pending elements yet to be sent.
  257. *
  258. * The xmppStreamDidDisconnect:withError: delegate method will immediately be dispatched onto the delegate queue.
  259. **/
  260. - (void)disconnect;
  261. /**
  262. * Disconnects from the remote host by sending the terminating </stream:stream> element,
  263. * and then closing the underlying TCP socket connection.
  264. *
  265. * This method is asynchronous.
  266. * The disconnect will happen after all pending elements have been sent.
  267. * Attempting to send elements after this method has been called will not work (the elements won't get sent).
  268. **/
  269. - (void)disconnectAfterSending;
  270. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  271. #pragma mark Security
  272. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  273. /**
  274. * Returns YES if SSL/TLS was used to establish a connection to the server.
  275. *
  276. * Some servers may require an "upgrade to TLS" in order to start communication,
  277. * so even if the connection was not explicitly secured, an ugrade to TLS may have occured.
  278. *
  279. * See also the xmppStream:willSecureWithSettings: delegate method.
  280. **/
  281. - (BOOL)isSecure;
  282. /**
  283. * Returns whether or not the server supports securing the connection via SSL/TLS.
  284. *
  285. * Some servers will actually require a secure connection,
  286. * in which case the stream will attempt to secure the connection during the opening process.
  287. *
  288. * If the connection has already been secured, this method may return NO.
  289. **/
  290. - (BOOL)supportsStartTLS;
  291. /**
  292. * Attempts to secure the connection via SSL/TLS.
  293. *
  294. * This method is asynchronous.
  295. * The SSL/TLS handshake will occur in the background, and
  296. * the xmppStreamDidSecure: delegate method will be called after the TLS process has completed.
  297. *
  298. * This method returns immediately.
  299. * If the secure process was started, it will return YES.
  300. * If there was an issue while starting the security process,
  301. * this method will return NO and set the error parameter.
  302. *
  303. * The errPtr parameter is optional - you may pass nil.
  304. *
  305. * You may wish to configure the security settings via the xmppStream:willSecureWithSettings: delegate method.
  306. *
  307. * If the SSL/TLS handshake fails, the connection will be closed.
  308. * The reason for the error will be reported via the xmppStreamDidDisconnect:withError: delegate method.
  309. * The error parameter will be an NSError object, and may have an error domain of kCFStreamErrorDomainSSL.
  310. * The corresponding error code is documented in Apple's Security framework, in SecureTransport.h
  311. **/
  312. - (BOOL)secureConnection:(NSError **)errPtr;
  313. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  314. #pragma mark Registration
  315. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  316. /**
  317. * In Band Registration.
  318. * Creating a user account on the xmpp server within the xmpp protocol.
  319. *
  320. * The registerWithPassword:error: method is asynchronous.
  321. * It will return immediately, and the delegate methods are used to determine success.
  322. * See the xmppStreamDidRegister: and xmppStream:didNotRegister: methods.
  323. *
  324. * If there is something immediately wrong, such as the stream is not connected,
  325. * this method will return NO and set the error.
  326. *
  327. * The errPtr parameter is optional - you may pass nil.
  328. *
  329. * Security Note:
  330. * The password will be sent in the clear unless the stream has been secured.
  331. **/
  332. - (BOOL)supportsInBandRegistration;
  333. - (BOOL)registerWithPassword:(NSString *)password error:(NSError **)errPtr;
  334. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  335. #pragma mark Authentication
  336. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  337. /**
  338. * Returns the server's list of supported authentication mechanisms.
  339. * Each item in the array will be of type NSString.
  340. *
  341. * For example, if the server supplied this stanza within it's reported stream:features:
  342. *
  343. * <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
  344. * <mechanism>DIGEST-MD5</mechanism>
  345. * <mechanism>PLAIN</mechanism>
  346. * </mechanisms>
  347. *
  348. * Then this method would return [@"DIGEST-MD5", @"PLAIN"].
  349. **/
  350. - (NSArray *)supportedAuthenticationMechanisms;
  351. /**
  352. * Returns whether or not the given authentication mechanism name was specified in the
  353. * server's list of supported authentication mechanisms.
  354. *
  355. * Note: The authentication classes often provide a category on XMPPStream, adding useful methods.
  356. *
  357. * @see XMPPPlainAuthentication - supportsPlainAuthentication
  358. * @see XMPPDigestMD5Authentication - supportsDigestMD5Authentication
  359. * @see XMPPXFacebookPlatformAuthentication - supportsXFacebookPlatformAuthentication
  360. * @see XMPPDeprecatedPlainAuthentication - supportsDeprecatedPlainAuthentication
  361. * @see XMPPDeprecatedDigestAuthentication - supportsDeprecatedDigestAuthentication
  362. **/
  363. - (BOOL)supportsAuthenticationMechanism:(NSString *)mechanism;
  364. /**
  365. * This is the root authentication method.
  366. * All other authentication methods go through this one.
  367. *
  368. * This method attempts to start the authentication process given the auth instance.
  369. * That is, this method will invoke start: on the given auth instance.
  370. * If it returns YES, then the stream will enter into authentication mode.
  371. * It will then continually invoke the handleAuth: method on the given instance until authentication is complete.
  372. *
  373. * This method is asynchronous.
  374. *
  375. * If there is something immediately wrong, such as the stream is not connected,
  376. * the method will return NO and set the error.
  377. * Otherwise the delegate callbacks are used to communicate auth success or failure.
  378. *
  379. * @see xmppStreamDidAuthenticate:
  380. * @see xmppStream:didNotAuthenticate:
  381. *
  382. * @see authenticateWithPassword:error:
  383. *
  384. * Note: The security process is abstracted in order to provide flexibility,
  385. * and allow developers to easily implement their own custom authentication protocols.
  386. * The authentication classes often provide a category on XMPPStream, adding useful methods.
  387. *
  388. * @see XMPPXFacebookPlatformAuthentication - authenticateWithFacebookAccessToken:error:
  389. **/
  390. - (BOOL)authenticate:(id <XMPPSASLAuthentication>)auth error:(NSError **)errPtr;
  391. /**
  392. * This method applies to standard password authentication schemes only.
  393. * This is NOT the primary authentication method.
  394. *
  395. * @see authenticate:error:
  396. *
  397. * This method exists for backwards compatibility, and may disappear in future versions.
  398. **/
  399. - (BOOL)authenticateWithPassword:(NSString *)password error:(NSError **)errPtr;
  400. /**
  401. * Returns whether or not the xmpp stream has successfully authenticated with the server.
  402. **/
  403. - (BOOL)isAuthenticated;
  404. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  405. #pragma mark Server Info
  406. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  407. /**
  408. * This method will return the root element of the document.
  409. * This element contains the opening <stream:stream/> and <stream:features/> tags received from the server.
  410. *
  411. * If multiple <stream:features/> have been received during the course of stream negotiation,
  412. * the root element contains only the most recent (current) version.
  413. *
  414. * Note: The rootElement is "empty", in-so-far as it does not contain all the XML elements the stream has
  415. * received during it's connection. This is done for performance reasons and for the obvious benefit
  416. * of being more memory efficient.
  417. **/
  418. - (NSXMLElement *)rootElement;
  419. /**
  420. * Returns the version attribute from the servers's <stream:stream/> element.
  421. * This should be at least 1.0 to be RFC 3920 compliant.
  422. * If no version number was set, the server is not RFC compliant, and 0 is returned.
  423. **/
  424. - (float)serverXmppStreamVersionNumber;
  425. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  426. #pragma mark Sending
  427. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  428. /**
  429. * Sends the given XML element.
  430. * If the stream is not yet connected, this method does nothing.
  431. **/
  432. - (void)sendElement:(NSXMLElement *)element;
  433. /**
  434. * Just like the sendElement: method above,
  435. * but allows you to receive a receipt that can later be used to verify the element has been sent.
  436. *
  437. * If you later want to check to see if the element has been sent:
  438. *
  439. * if ([receipt wait:0]) {
  440. * // Element has been sent
  441. * }
  442. *
  443. * If you later want to wait until the element has been sent:
  444. *
  445. * if ([receipt wait:-1]) {
  446. * // Element was sent
  447. * } else {
  448. * // Element failed to send due to disconnection
  449. * }
  450. *
  451. * It is important to understand what it means when [receipt wait:timeout] returns YES.
  452. * It does NOT mean the server has received the element.
  453. * It only means the data has been queued for sending in the underlying OS socket buffer.
  454. *
  455. * So at this point the OS will do everything in its capacity to send the data to the server,
  456. * which generally means the server will eventually receive the data.
  457. * Unless, of course, something horrible happens such as a network failure,
  458. * or a system crash, or the server crashes, etc.
  459. *
  460. * Even if you close the xmpp stream after this point, the OS will still do everything it can to send the data.
  461. **/
  462. - (void)sendElement:(NSXMLElement *)element andGetReceipt:(XMPPElementReceipt **)receiptPtr;
  463. /**
  464. * Fetches and resends the myPresence element (if available) in a single atomic operation.
  465. *
  466. * There are various xmpp extensions that hook into the xmpp stream and append information to outgoing presence stanzas.
  467. * For example, the XMPPCapabilities module automatically appends capabilities information (as a hash).
  468. * When these modules need to update/change their appended information,
  469. * they should use this method to do so.
  470. *
  471. * The alternative is to fetch the myPresence element, and resend it manually using the sendElement method.
  472. * However, that is 2 seperate operations, and the user, may send a different presence element inbetween.
  473. * Using this method guarantees everything is done as an atomic operation.
  474. **/
  475. - (void)resendMyPresence;
  476. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  477. #pragma mark Module Plug-In System
  478. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  479. /**
  480. * The XMPPModule class automatically invokes these methods when it is activated/deactivated.
  481. *
  482. * The registerModule method registers the module with the xmppStream.
  483. * If there are any other modules that have requested to be automatically added as delegates to modules of this type,
  484. * then those modules are automatically added as delegates during the asynchronous execution of this method.
  485. *
  486. * The registerModule method is asynchronous.
  487. *
  488. * The unregisterModule method unregisters the module with the xmppStream,
  489. * and automatically removes it as a delegate of any other module.
  490. *
  491. * The unregisterModule method is fully synchronous.
  492. * That is, after this method returns, the module will not be scheduled in any more delegate calls from other modules.
  493. * However, if the module was already scheduled in an existing asynchronous delegate call from another module,
  494. * the scheduled delegate invocation remains queued and will fire in the near future.
  495. * Since the delegate invocation is already queued,
  496. * the module's retainCount has been incremented,
  497. * and the module will not be deallocated until after the delegate invocation has fired.
  498. **/
  499. - (void)registerModule:(XMPPModule *)module;
  500. - (void)unregisterModule:(XMPPModule *)module;
  501. /**
  502. * Automatically registers the given delegate with all current and future registered modules of the given class.
  503. *
  504. * That is, the given delegate will be added to the delegate list ([module addDelegate:delegate delegateQueue:dq]) to
  505. * all current and future registered modules that respond YES to [module isKindOfClass:aClass].
  506. *
  507. * This method is used by modules to automatically integrate with other modules.
  508. * For example, a module may auto-add itself as a delegate to XMPPCapabilities
  509. * so that it can broadcast its implemented features.
  510. *
  511. * This may also be useful to clients, for example, to add a delegate to instances of something like XMPPChatRoom,
  512. * where there may be multiple instances of the module that get created during the course of an xmpp session.
  513. *
  514. * If you auto register on multiple queues, you can remove all registrations with a single
  515. * call to removeAutoDelegate::: by passing NULL as the 'dq' parameter.
  516. *
  517. * If you auto register for multiple classes, you can remove all registrations with a single
  518. * call to removeAutoDelegate::: by passing nil as the 'aClass' parameter.
  519. **/
  520. - (void)autoAddDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue toModulesOfClass:(Class)aClass;
  521. - (void)removeAutoDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue fromModulesOfClass:(Class)aClass;
  522. /**
  523. * Allows for enumeration of the currently registered modules.
  524. *
  525. * This may be useful if the stream needs to be queried for modules of a particular type.
  526. **/
  527. - (void)enumerateModulesWithBlock:(void (^)(XMPPModule *module, NSUInteger idx, BOOL *stop))block;
  528. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  529. #pragma mark Utilities
  530. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  531. /**
  532. * Generates and returns a new autoreleased UUID.
  533. * UUIDs (Universally Unique Identifiers) may also be known as GUIDs (Globally Unique Identifiers).
  534. *
  535. * The UUID is generated using the CFUUID library, which generates a unique 128 bit value.
  536. * The uuid is then translated into a string using the standard format for UUIDs:
  537. * "68753A44-4D6F-1226-9C60-0050E4C00067"
  538. *
  539. * This method is most commonly used to generate a unique id value for an xmpp element.
  540. **/
  541. + (NSString *)generateUUID;
  542. - (NSString *)generateUUID;
  543. /**
  544. * The XMPP Framework is designed to be entirely GCD based.
  545. * However, there are various utility classes provided by Apple that are still dependent upon a thread/runloop model.
  546. * For example, monitoring a network for changes related to connectivity requires we register a runloop-based delegate.
  547. * Thus XMPPStream creates a dedicated thread/runloop for any xmpp classes that may need it.
  548. * This provides multiple benefits:
  549. *
  550. * - Development is simplified for those transitioning from previous thread/runloop versions.
  551. * - Development is simplified for those who rely on utility classes that don't yet support pure GCD,
  552. * as they don't have to setup and maintain a thread/runloop on their own.
  553. * - It prevents multiple xmpp classes from creating multiple internal threads (which would be resource costly).
  554. *
  555. * Please note:
  556. * This thread is designed to be used only if absolutely necessary.
  557. * That is, if you MUST use a class that doesn't yet support pure GCD.
  558. * If there is a GCD alternative, you should be using it instead.
  559. * For example, do NOT use NSTimer. Instead setup a GCD timer using a dispatch_source.
  560. **/
  561. - (NSThread *)xmppUtilityThread;
  562. - (NSRunLoop *)xmppUtilityRunLoop;
  563. @end
  564. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  565. #pragma mark -
  566. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  567. @interface XMPPElementReceipt : NSObject
  568. {
  569. uint32_t atomicFlags;
  570. dispatch_semaphore_t semaphore;
  571. }
  572. /**
  573. * Element receipts allow you to check to see if the element has been sent.
  574. * The timeout parameter allows you to do any of the following:
  575. *
  576. * - Do an instantaneous check (pass timeout == 0)
  577. * - Wait until the element has been sent (pass timeout < 0)
  578. * - Wait up to a certain amount of time (pass timeout > 0)
  579. *
  580. * It is important to understand what it means when [receipt wait:timeout] returns YES.
  581. * It does NOT mean the server has received the element.
  582. * It only means the data has been queued for sending in the underlying OS socket buffer.
  583. *
  584. * So at this point the OS will do everything in its capacity to send the data to the server,
  585. * which generally means the server will eventually receive the data.
  586. * Unless, of course, something horrible happens such as a network failure,
  587. * or a system crash, or the server crashes, etc.
  588. *
  589. * Even if you close the xmpp stream after this point, the OS will still do everything it can to send the data.
  590. **/
  591. - (BOOL)wait:(NSTimeInterval)timeout;
  592. @end
  593. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  594. #pragma mark -
  595. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  596. @protocol XMPPStreamDelegate
  597. @optional
  598. /**
  599. * This method is called before the stream begins the connection process.
  600. *
  601. * If developing an iOS app that runs in the background, this may be a good place to indicate
  602. * that this is a task that needs to continue running in the background.
  603. **/
  604. - (void)xmppStreamWillConnect:(XMPPStream *)sender;
  605. /**
  606. * This method is called after the tcp socket has connected to the remote host.
  607. * It may be used as a hook for various things, such as updating the UI or extracting the server's IP address.
  608. *
  609. * If developing an iOS app that runs in the background,
  610. * please use XMPPStream's enableBackgroundingOnSocket property as opposed to doing it directly on the socket here.
  611. **/
  612. - (void)xmppStream:(XMPPStream *)sender socketDidConnect:(GCDAsyncSocket *)socket;
  613. /**
  614. * This method is called after a TCP connection has been established with the server,
  615. * and the opening XML stream negotiation has started.
  616. **/
  617. - (void)xmppStreamDidStartNegotiation:(XMPPStream *)sender;
  618. /**
  619. * This method is called immediately prior to the stream being secured via TLS/SSL.
  620. * Note that this delegate may be called even if you do not explicitly invoke the startTLS method.
  621. * Servers have the option of requiring connections to be secured during the opening process.
  622. * If this is the case, the XMPPStream will automatically attempt to properly secure the connection.
  623. *
  624. * The possible keys and values for the security settings are well documented.
  625. * Some possible keys are:
  626. * - kCFStreamSSLLevel
  627. * - kCFStreamSSLAllowsExpiredCertificates
  628. * - kCFStreamSSLAllowsExpiredRoots
  629. * - kCFStreamSSLAllowsAnyRoot
  630. * - kCFStreamSSLValidatesCertificateChain
  631. * - kCFStreamSSLPeerName
  632. * - kCFStreamSSLCertificates
  633. *
  634. * Please refer to Apple's documentation for associated values, as well as other possible keys.
  635. *
  636. * The dictionary of settings is what will be passed to the startTLS method of ther underlying AsyncSocket.
  637. * The AsyncSocket header file also contains a discussion of the security consequences of various options.
  638. * It is recommended reading if you are planning on implementing this method.
  639. *
  640. * The dictionary of settings that are initially passed will be an empty dictionary.
  641. * If you choose not to implement this method, or simply do not edit the dictionary,
  642. * then the default settings will be used.
  643. * That is, the kCFStreamSSLPeerName will be set to the configured host name,
  644. * and the default security validation checks will be performed.
  645. *
  646. * This means that authentication will fail if the name on the X509 certificate of
  647. * the server does not match the value of the hostname for the xmpp stream.
  648. * It will also fail if the certificate is self-signed, or if it is expired, etc.
  649. *
  650. * These settings are most likely the right fit for most production environments,
  651. * but may need to be tweaked for development or testing,
  652. * where the development server may be using a self-signed certificate.
  653. **/
  654. - (void)xmppStream:(XMPPStream *)sender willSecureWithSettings:(NSMutableDictionary *)settings;
  655. /**
  656. * This method is called after the stream has been secured via SSL/TLS.
  657. * This method may be called if the server required a secure connection during the opening process,
  658. * or if the secureConnection: method was manually invoked.
  659. **/
  660. - (void)xmppStreamDidSecure:(XMPPStream *)sender;
  661. /**
  662. * This method is called after the XML stream has been fully opened.
  663. * More precisely, this method is called after an opening <xml/> and <stream:stream/> tag have been sent and received,
  664. * and after the stream features have been received, and any required features have been fullfilled.
  665. * At this point it's safe to begin communication with the server.
  666. **/
  667. - (void)xmppStreamDidConnect:(XMPPStream *)sender;
  668. /**
  669. * This method is called after registration of a new user has successfully finished.
  670. * If registration fails for some reason, the xmppStream:didNotRegister: method will be called instead.
  671. **/
  672. - (void)xmppStreamDidRegister:(XMPPStream *)sender;
  673. /**
  674. * This method is called if registration fails.
  675. **/
  676. - (void)xmppStream:(XMPPStream *)sender didNotRegister:(NSXMLElement *)error;
  677. /**
  678. * This method is called after authentication has successfully finished.
  679. * If authentication fails for some reason, the xmppStream:didNotAuthenticate: method will be called instead.
  680. **/
  681. - (void)xmppStreamDidAuthenticate:(XMPPStream *)sender;
  682. /**
  683. * This method is called if authentication fails.
  684. **/
  685. - (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(NSXMLElement *)error;
  686. /**
  687. * This method is called if the XMPP server doesn't allow our resource of choice
  688. * because it conflicts with an existing resource.
  689. *
  690. * Return an alternative resource or return nil to let the server automatically pick a resource for us.
  691. **/
  692. - (NSString *)xmppStream:(XMPPStream *)sender alternativeResourceForConflictingResource:(NSString *)conflictingResource;
  693. /**
  694. * These methods are called before their respective XML elements are broadcast as received to the rest of the stack.
  695. * These methods can be used to modify elements on the fly.
  696. * (E.g. perform custom decryption so the rest of the stack sees readable text.)
  697. *
  698. * You may also filter incoming elements by returning nil.
  699. *
  700. * When implementing these methods to modify the element, you do not need to copy the given element.
  701. * You can simply edit the given element, and return it.
  702. * The reason these methods return an element, instead of void, is to allow filtering.
  703. *
  704. * Concerning thread-safety, delegates implementing the method are invoked one-at-a-time to
  705. * allow thread-safe modification of the given elements.
  706. *
  707. * You should NOT implement these methods unless you have good reason to do so.
  708. * For general processing and notification of received elements, please use xmppStream:didReceiveX: methods.
  709. *
  710. * @see xmppStream:didReceiveIQ:
  711. * @see xmppStream:didReceiveMessage:
  712. * @see xmppStream:didReceivePresence:
  713. **/
  714. - (XMPPIQ *)xmppStream:(XMPPStream *)sender willReceiveIQ:(XMPPIQ *)iq;
  715. - (XMPPMessage *)xmppStream:(XMPPStream *)sender willReceiveMessage:(XMPPMessage *)message;
  716. - (XMPPPresence *)xmppStream:(XMPPStream *)sender willReceivePresence:(XMPPPresence *)presence;
  717. /**
  718. * These methods are called after their respective XML elements are received on the stream.
  719. *
  720. * In the case of an IQ, the delegate method should return YES if it has or will respond to the given IQ.
  721. * If the IQ is of type 'get' or 'set', and no delegates respond to the IQ,
  722. * then xmpp stream will automatically send an error response.
  723. *
  724. * Concerning thread-safety, delegates shouldn't modify the given elements.
  725. * As documented in NSXML / KissXML, elements are read-access thread-safe, but write-access thread-unsafe.
  726. * If you have need to modify an element for any reason,
  727. * you should copy the element first, and then modify and use the copy.
  728. **/
  729. - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq;
  730. - (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message;
  731. - (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence;
  732. /**
  733. * This method is called if an XMPP error is received.
  734. * In other words, a <stream:error/>.
  735. *
  736. * However, this method may also be called for any unrecognized xml stanzas.
  737. *
  738. * Note that standard errors (<iq type='error'/> for example) are delivered normally,
  739. * via the other didReceive...: methods.
  740. **/
  741. - (void)xmppStream:(XMPPStream *)sender didReceiveError:(NSXMLElement *)error;
  742. /**
  743. * These methods are called before their respective XML elements are sent over the stream.
  744. * These methods can be used to modify outgoing elements on the fly.
  745. * (E.g. add standard information for custom protocols.)
  746. *
  747. * You may also filter outgoing elements by returning nil.
  748. *
  749. * When implementing these methods to modify the element, you do not need to copy the given element.
  750. * You can simply edit the given element, and return it.
  751. * The reason these methods return an element, instead of void, is to allow filtering.
  752. *
  753. * Concerning thread-safety, delegates implementing the method are invoked one-at-a-time to
  754. * allow thread-safe modification of the given elements.
  755. *
  756. * You should NOT implement these methods unless you have good reason to do so.
  757. * For general processing and notification of sent elements, please use xmppStream:didSendX: methods.
  758. *
  759. * @see xmppStream:didSendIQ:
  760. * @see xmppStream:didSendMessage:
  761. * @see xmppStream:didSendPresence:
  762. **/
  763. - (XMPPIQ *)xmppStream:(XMPPStream *)sender willSendIQ:(XMPPIQ *)iq;
  764. - (XMPPMessage *)xmppStream:(XMPPStream *)sender willSendMessage:(XMPPMessage *)message;
  765. - (XMPPPresence *)xmppStream:(XMPPStream *)sender willSendPresence:(XMPPPresence *)presence;
  766. /**
  767. * These methods are called after their respective XML elements are sent over the stream.
  768. * These methods may be used to listen for certain events (such as an unavailable presence having been sent),
  769. * or for general logging purposes. (E.g. a central history logging mechanism).
  770. **/
  771. - (void)xmppStream:(XMPPStream *)sender didSendIQ:(XMPPIQ *)iq;
  772. - (void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message;
  773. - (void)xmppStream:(XMPPStream *)sender didSendPresence:(XMPPPresence *)presence;
  774. /**
  775. * This method is called if the disconnect method is called.
  776. * It may be used to determine if a disconnection was purposeful, or due to an error.
  777. **/
  778. - (void)xmppStreamWasToldToDisconnect:(XMPPStream *)sender;
  779. /**
  780. * This method is called after the stream is closed.
  781. *
  782. * The given error parameter will be non-nil if the error was due to something outside the general xmpp realm.
  783. * Some examples:
  784. * - The TCP socket was unexpectedly disconnected.
  785. * - The SRV resolution of the domain failed.
  786. * - Error parsing xml sent from server.
  787. **/
  788. - (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error;
  789. /**
  790. * This method is only used in P2P mode when the connectTo:withAddress: method was used.
  791. *
  792. * It allows the delegate to read the <stream:features/> element if/when they arrive.
  793. * Recall that the XEP specifies that <stream:features/> SHOULD be sent.
  794. **/
  795. - (void)xmppStream:(XMPPStream *)sender didReceiveP2PFeatures:(NSXMLElement *)streamFeatures;
  796. /**
  797. * This method is only used in P2P mode when the connectTo:withSocket: method was used.
  798. *
  799. * It allows the delegate to customize the <stream:features/> element,
  800. * adding any specific featues the delegate might support.
  801. **/
  802. - (void)xmppStream:(XMPPStream *)sender willSendP2PFeatures:(NSXMLElement *)streamFeatures;
  803. /**
  804. * These methods are called as xmpp modules are registered and unregistered with the stream.
  805. * This generally corresponds to xmpp modules being initailzed and deallocated.
  806. *
  807. * The methods may be useful, for example, if a more precise auto delegation mechanism is needed
  808. * than what is available with the autoAddDelegate:toModulesOfClass: method.
  809. **/
  810. - (void)xmppStream:(XMPPStream *)sender didRegisterModule:(id)module;
  811. - (void)xmppStream:(XMPPStream *)sender willUnregisterModule:(id)module;
  812. @end