Search code examples
objective-cejabberdxmppframework

Process One Extension in XMPP Framework For ejabberd Fast Reconnect and Push Mode


I am having difficulty using one XMPPFramework Extension named ProcessOne that is made for ejabberd.

I am trying to use ProcessOne Extension For Fast Reconnect and Push Mode

// Process One Fast Reconnect & Push Standby Mode //

xmppProcessOne = [[XMPPProcessOne alloc] initWithDispatchQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)];
[xmppProcessOne addDelegate:self delegateQueue:dispatch_get_main_queue()];
xmppProcessOne.pushConfiguration = [self setPushconfiguration];
[xmppProcessOne activate:_xmppStream];

As per ejabberd documentation I have to send rebind packet after stream features confirmation. There is a method available in this extension under implementation of XMPPRebindAuthentication. I am unable to understand how I can invoke this method.


Solution

  • I do not think the code to support session rebind for Extensions/ProcessOne in XMPPFramework is complete and can work as is.

    Here is a patch I propose on XMPPFramework that should work: https://github.com/processone/XMPPFramework/commit/67a20c28b28ca49667ca11012bb2a11373023057

    At least I could make rebind work from there using the following example client:

    • AppDelegate.h
    //
    //  AppDelegate.h
    //
    //  Created by Mickaël Rémond on 07/03/16.
    //
    
    #import <UIKit/UIKit.h>
    
    #import <XMPPFramework/XMPPRoster.h>
    #import <XMPPFramework/XMPPRosterCoreDataStorage.h>
    #import <XMPPFramework/XMPPProcessOne.h>
    
    @interface AppDelegate : UIResponder <UIApplicationDelegate, XMPPRosterDelegate, XMPPStreamDelegate>
    
    @property (strong, nonatomic) UIWindow *window;
    
    /* XMPP related properties */
    @property (nonatomic, strong) XMPPStream *xmppStream;
    @property (nonatomic, strong) XMPPRoster *xmppRoster;
    @property (nonatomic, strong) XMPPProcessOne *xmppProcessOne;
    @property (nonatomic, strong) XMPPRosterCoreDataStorage *xmppRosterStorage;
    
    @end
    
    • AppDelegate.m
    //
    //  AppDelegate.m
    //
    //  Created by Mickaël Rémond on 07/03/16.
    //
    
    #import "AppDelegate.h"
    
    #import "DDLog.h"
    #import "DDTTYLogger.h"
    #import "XMPPLogging.h"
    
    @interface AppDelegate ()
    - (void)setupStream;
    - (BOOL)connect;
    @end
    
    @implementation AppDelegate
    
    static NSString * const kMyJid = @"[email protected]";
    static NSString * const kMyPass = @"passw0rd";
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // Log all XMPP traffic for debugging
        [DDLog addLogger:[DDTTYLogger sharedInstance] withLogLevel:XMPP_LOG_FLAG_SEND_RECV];
        [self setupStream];
    
        return YES;
    }
    
    - (void)applicationWillResignActive:(UIApplication *)application {
    }
    
    - (void)applicationDidEnterBackground:(UIApplication *)application {
    }
    
    - (void)applicationWillEnterForeground:(UIApplication *)application {
    }
    
    - (void)applicationDidBecomeActive:(UIApplication *)application {
        [self connect];
    }
    
    - (void)applicationWillTerminate:(UIApplication *)application {
    }
    
    #pragma mark == Setup XMPP parameters ==
    - (void)setupStream {
        _xmppStream = [XMPPStream new];
        _xmppRosterStorage = [XMPPRosterCoreDataStorage new];
        _xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:_xmppRosterStorage];
    
        [_xmppRoster activate:_xmppStream];
    
        [_xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
        [_xmppStream addDelegate:self.xmppProcessOne delegateQueue:dispatch_get_main_queue()];
        [_xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
        [_xmppStream setMyJID:[XMPPJID jidWithString:kMyJid]];
    
        _xmppProcessOne = [[XMPPProcessOne alloc] initWithDispatchQueue:dispatch_get_main_queue()];
        // TODO: Method to generate default push configuration
        NSXMLElement *pushConfiguration = [XMPPProcessOne pushConfigurationContainer];
        [pushConfiguration addChild:[XMPPProcessOne keepaliveWithMax:30]];     // Seconds
        [pushConfiguration addChild:[XMPPProcessOne sessionWithDuration:300]]; // Seconds
        _xmppProcessOne.pushConfiguration = pushConfiguration;
    
        [_xmppProcessOne addDelegate:self delegateQueue:dispatch_get_main_queue()];
        [_xmppProcessOne activate:self.xmppStream];
    }
    
    #pragma mark == XMPP DELEGATES ==
    - (void)xmppStreamDidConnect:(XMPPStream *)sender {
        if ([self.xmppStream supportsRebind] && self.xmppProcessOne.savedSessionJID != nil) {
            NSError *error = nil;
            _xmppRoster.autoFetchRoster = NO;
            if (![[self xmppStream] rebindSession:self.xmppProcessOne.savedSessionID forJID:self.xmppProcessOne.savedSessionJID withError:&error]) {
                NSLog(@"Could not send session rebind successfully: %@", error);
            }
        } else {
            NSError *error = nil;
            _xmppRoster.autoFetchRoster = YES;
            if (![[self xmppStream] authenticateWithPassword:kMyPass error:&error]) {
                NSLog(@"Could not send standard password auth info: %@", error);
            }
        }
    }
    
    // Rebind failed, try standard auth
    - (void)xmppStream:(XMPPStream *)sender runFallbackAuthentication:(NSXMLElement *)error {
        NSLog(@"Rebind failed: %@", error);
        NSError *error2 = nil;
        _xmppRoster.autoFetchRoster = YES;
        if (![[self xmppStream] authenticateWithPassword:kMyPass error:&error2]) {
            NSLog(@"did not authenticate %@", error2);
        }
    }
    
    - (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(NSXMLElement *)error {
        NSLog(@"Authentication failed: %@", error);
    }
    
    - (void)xmppStreamDidAuthenticate:(XMPPStream *)sender {
       NSLog(@"Authentication successfull");
       [[self xmppStream] sendElement:[XMPPPresence presence]];
    }
    
    /* Initiate TCP connection to XMPP server */
    - (BOOL)connect {
        if (!self.xmppStream.isConnected) {
            if (![self.xmppStream isDisconnected]) {
                return YES;
            }
    
            NSError *error = nil;
            if (![self.xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error]) {
                NSLog(@"Error connecting to XMPP server");
            } else {
                NSLog(@"Successfully connected");
            }
    
            return YES;
        } else {
            return YES;
        }
    }
    
    @end