Strophe Connection management BOSH + Openfire + iPhone

910 views
Skip to first unread message

Himanshu

unread,
Jun 9, 2011, 11:18:31 AM6/9/11
to Strophe
Hello -
We have a very strange issue at our hand. Our chat works absolutely
fine when used on wireless network on iPhone
When user is using 3G network in US, it gets too frequently
disconnected and re-connected again.
Due to the same his messages drop and do not get to the end user nor
does he receive the message.
In the end we end up making multiple connections and messages are not
received.
Has anyone faced any such issues? I will post our connection code in
reply to the message as well.
Thanks,
Himanshu

Himanshu Khona

unread,
Jun 9, 2011, 1:58:29 PM6/9/11
to Strophe
Hi 
On that note, is there a way we can a deliver confirmation of the message?
Thanks,
Himanshu


--
You received this message because you are subscribed to the Google Groups "Strophe" group.
To post to this group, send email to str...@googlegroups.com.
To unsubscribe from this group, send email to strophe+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/strophe?hl=en.


Himanshu Khona

unread,
Jun 10, 2011, 4:25:04 AM6/10/11
to Strophe
Here is the connection management code -

Chat.connection.connect(username+"@"+Chat.DOMAIN, password, function(status){

if (status === Strophe.Status.CONNECTED) {

if(existsData("rooms"))

{

var rooms = selectData("rooms");

var roomArray = rooms.split(",");

var roomLength = roomArray.length;

for(var i = 0; i<roomLength; i++)

{

Chat.joinRoom(roomArray[i]+"@"+Chat.CONFERENCE_SERVICE);

}

}

                //setting own presence as online

                Chat.connection.send($pres({

                    from:username+"@"+Chat.DOMAIN

                }).c("priority",{}).cnode(Strophe.xmlTextNode("1")).tree());


                //Setting variables

                Chat.friendlyName = username;

                Chat.jid = Chat.connection.jid;

                Chat.sid = Chat.connection.sid;

                Chat.rid = Chat.connection.rid;

                //Setting listener for message, group message, invitation etc

                Chat.setUpHandler();

setTimeout(function() {

$('#transparentLoadingGrid').css('display', 'none');

$('#transparentLoadingGrid').css('z-index', '-1');

$('#transparentLoadingGrid').css('visibility', 'hidden');

//$('#attach-options').css('top', '224px');

    }, 2000);

User.getFriends();

Chat.addFriends(User.myFriends);

User.setDefaultStatus();

if(callback && typeof(callback)==="function")

{

if(args != null && args != undefined)

{

callback(args)


}

else

{

callback();

}

}

            } else if (status === Strophe.Status.DISCONNECTED) {

                //alert("ReConnecting again...");

                User.getProfile();

Chat.doConnection();

                Chat.doLogin(User.userProfileobj.twentyatUserId, User.userProfileobj.email);

//trigger UI to disable chat

setTimeout(function() {

  $('#transparentLoadingGrid').css('display', 'none');

  $('#transparentLoadingGrid').css('z-index', '-1');

  $('#transparentLoadingGrid').css('visibility', 'hidden');

  //$('#attach-options').css('top', '224px');

}, 2000);

User.getFriends();

}

If presence is found offline, re-connect before sending the message -

doDisconnect : function()

    {

$.ajax({

url: "http://"+Chat.DOMAIN+":9090/plugins/presence/status",

dataType : "jsonp",    

contentType: "application/json",

type : "GET",    

data : {"jid":User.userProfileobj.twentyatUserId+"@"+Chat.DOMAIN, "type":"json"},

success : function(status)

{

  if(status.presence === "offline")

  {

Chat.connection == null;

User.getConnection();

  }

  else

  {

  if(Chat.connection != null)

  {

  Chat.connection.sync = true; // Switch to using synchronous requests since this is typically called onUnload.

  Chat.connection.disconnect();

  Chat.connection.flush();

  Chat.connection = null;

  }

  else

  {

  Chat.connection == null;

  User.getConnection();

  }    

  }

},

error : function(error)

{

  if(Chat.connection != null)

  {

  Chat.connection.sync = true; // Switch to using synchronous requests since this is typically called onUnload.

  Chat.connection.disconnect();

  Chat.connection.flush();

  Chat.connection = null;

  }

  else

  {

  Chat.connection == null;

  User.getConnection();

  }

}

});


On resume disconnect, the connection is done automatically by code in begining -

function onResume() 

{

try

{

    Chat.doDisconnect();

$('#transparentLoadingGrid').css('display', 'block');

$('#transparentLoadingGrid').css('z-index', '10000');

$('#transparentLoadingGrid').css('visibility', 'visible');

//Chat.connection = null;

//User.getConnection();

}

catch(e)

{

//alert(e);

}

}

Let me know if you have any questions.

Thanks for your help!

BR,

Himanshu

Ilya Braude

unread,
Jun 10, 2011, 9:57:08 AM6/10/11
to str...@googlegroups.com

On 06/09/2011 01:58 PM, Himanshu Khona wrote:
> Hi
> On that note, is there a way we can a deliver confirmation of the message?

There's an implicit acking mechanism when using BOSH. If the BOSH HTTP
request to the server comes back succesfully, then you can assume that
all stanzas in that request made it to the server. What you can do is
add send/receive hooks into Strophe that will keep track of which
stanzas failed to be sent (add all outgoing stanzas to a list, and
remove them when the response comes back). Then you can re-send
unsuccessful stanzas on reconnection.

Also, there's XEP-0198 that supports acks at the XMPP level, but does
not yet have widespread server support.

Ilya

Himanshu Khona

unread,
Jun 10, 2011, 10:53:01 AM6/10/11
to str...@googlegroups.com
Thanks!
Actually we figured the actual issue is connection management. So if the device/user gets disconnected, we get him to login but since connectivity is weak user gets disconnected again.
Under such circumstances, what action is to be taken to make it stable?
I am sure XMPP and strophe are widely used in production chat application on phones too so how is this handled?
Below is the code, I am talking about -

if (status === Strophe.Status.DISCONNECTED) {

                //alert("ReConnecting again...");

                User.getProfile();

Chat.doConnection();

                Chat.doLogin(User.userProfileobj.twentyatUserId, User.userProfileobj.email);


Thanks,

Himanshu




--

Himanshu Khona

unread,
Jun 10, 2011, 11:24:38 AM6/10/11
to str...@googlegroups.com
Basically this creates a loop and user actually never gets online and has many authenticated/offline connections.
Even if we have mechanism to tell user that his messages cannot be send now, that should suffice.
Thanks,
Himanshu

Ilya Braude

unread,
Jun 10, 2011, 11:24:16 AM6/10/11
to str...@googlegroups.com

On 06/10/2011 10:53 AM, Himanshu Khona wrote:
> Actually we figured the actual issue is connection management. So if
> the device/user gets disconnected, we get him to login but since
> connectivity is weak user gets disconnected again.
> Under such circumstances, what action is to be taken to make it stable?

I don't think there's much you can do about a bad network connection.
The best you can do is to handle frequent disconnects and make sure that
you don't lose any messages. If you like, I can point you to a
connection manager plugin that I wrote that does the BOSH acking that I
described. It works well for us on mobile networks.

> I am sure XMPP and strophe are widely used in production chat
> application on phones too so how is this handled?
> Below is the code, I am talking about -
> if (status === Strophe.Status.DISCONNECTED) {
>
> //alert("ReConnecting again...");
>
> User.getProfile();
>
> Chat.doConnection();
>
> Chat.doLogin(User.userProfileobj.twentyatUserId,
> User.userProfileobj.email);
>

It's not clear to me what your code is doing. It looks like you are
making synchronous calls to functions that should probably be
asynchronous. Do User.getProfile() and Chat.doConnection() make network
calls?

Also, your code to send presence can be simplified to just:
Chat.connection.send($pres().c("priority").t("1").tree());


Ilya

Himanshu Khona

unread,
Jun 10, 2011, 12:22:54 PM6/10/11
to str...@googlegroups.com
Hello -
Thanks for your response.
My response inline.

I don't think there's much you can do about a bad network connection.  The best you can do is to handle frequent disconnects and make sure that you don't lose any messages.  If you like, I can point you to a connection manager plugin that I wrote that does the BOSH acking that I described.  It works well for us on mobile networks.
>>>> How to not loose any messages is the main thing ;)??
>>>>Please point me to the connection manager plugin.


I am sure XMPP and strophe are widely used in production chat application on phones too so how is this handled?
Below is the code, I am talking about -
if (status === Strophe.Status.DISCONNECTED) {

//alert("ReConnecting again...");

               User.getProfile();

Chat.doConnection();

               Chat.doLogin(User.userProfileobj.twentyatUserId, User.userProfileobj.email);


It's not clear to me what your code is doing.  It looks like you are making synchronous calls to functions that should probably be asynchronous.  Do User.getProfile() and Chat.doConnection() make network calls?
>>>>> None of them make network calls, get profile gets username/password for login and do connection creates a connection object.


Also, your code to send presence can be simplified to just:
Chat.connection.send($pres().c("priority").t("1").tree());
>>>> That makes sense.
Thanks,
Himanshu
 





Ilya

Himanshu Khona

unread,
Jun 10, 2011, 1:12:39 PM6/10/11
to str...@googlegroups.com
Just saw this post - http://stackoverflow.com/questions/2708564/dealing-with-missing-messages-in-javascript-when-using-bosh
Jack - Does strophe already provide acking mechanism?
Thanks,
Himanshu

Ilya Braude

unread,
Jun 10, 2011, 1:39:47 PM6/10/11
to str...@googlegroups.com

On 06/10/2011 12:22 PM, Himanshu Khona wrote:
I don't think there's much you can do about a bad network connection.  The best you can do is to handle frequent disconnects and make sure that you don't lose any messages.  If you like, I can point you to a connection manager plugin that I wrote that does the BOSH acking that I described.  It works well for us on mobile networks.
>>>> How to not loose any messages is the main thing ;)??
>>>>Please point me to the connection manager plugin.

https://github.com/zanchin/strophejs/blob/master/plugins/plugin.cm.js

This actually does two things: pings the server at regular intervals and disconnects/reconnects when server doesn't respond.
It also keeps track of all unsent stanzas and resends them when reconnected.  Here's how you configure it:

Take a look at the 'config' object in the plugin for settings that you can override.

connection.connectionmanager.configure({
        autoResend: true,  // resend all unsent stanzas immediately on reconnection
        onDequeueElement: function(el){
            // called with the stanza element 'el' when it's "ack"ed.
        },
        onReceiveTimeout: function(){
          // called when server ping times out
        },
        onPingOK: function(){
          // called on successful ping response from the server
        }
    });


The plugin will not prevent message loss for all cases.  It's possible that incoming messages can still get lost between the BOSH connection manager and the browser.  Only way to handle that is to use XMPP-level acks (as per XEP-0198).



I am sure XMPP and strophe are widely used in production chat application on phones too so how is this handled?
Below is the code, I am talking about -
if (status === Strophe.Status.DISCONNECTED) {

//alert("ReConnecting again...");

               User.getProfile();

Chat.doConnection();

               Chat.doLogin(User.userProfileobj.twentyatUserId, User.userProfileobj.email);


It's not clear to me what your code is doing.  It looks like you are making synchronous calls to functions that should probably be asynchronous.  Do User.getProfile() and Chat.doConnection() make network calls?
>>>>> None of them make network calls, get profile gets username/password for login and do connection creates a connection object.

Ah, ok.  Just a bit strange that all work is done through side effects.


Ilya


Reply all
Reply to author
Forward
0 new messages