Introduction
I am working on an MVC web app that is using XMPP for two purposes: 1) Communicating real time data from the server to the client - XMPPMessaging 2) User group chat - XMPPChat
I am using Strophe.js on the client side and MatriX C# library on the server side. XMPPChat is being set up by prebinding on the server side and passing the connection info to the client, which attaches with strophe. XMPPMessaging is not prebinding, just logging in on the client side. Every window that the user opens connects a new XMPPMessaging instance to receive data from the server. Only the chat windows connect XMPPChat and XMPPMessaging. Also, both are connecting to the Punjab connection manager over BOSH, which is forwarding the messages to an Openfire server.
Issue
Currently, I have an issue that only manifests itself in Internet Explorer (I am testing with IE8 and IE9 and both exibit this issue). When I have XMPPMessaging and XMPPChat connected, chat messages are being sent after a very large delay (10 sec - 2 minutes). I've seen this cause disconnection issues for XMPPChat as well. The receive functionality works great; if any other browser posts to the chatroom, IE get's it immediately just like everyone else. When XMPPMessaging is turned off, the chat send runs great with no delays or disconnections. I've stepped through the code with breakpoints and the send functionality is firing immediately. I've also observed the Punjab logs, and it appears that Punjab isn't getting the message till after the delay and is passing them along fine (also evidenced by the other browsers working fine).
I'm mostly wondering if anyone else has seen issues like this one with concurrent BOSH connections in IE comehow interfering.
Update
The chat feature in IE started working today completely inexplicably; I haven't changed the code or any configuration of it at all. I double checked that the messaging connection and chat connection were both running, and they both were connected. In attempts to diagnose the fix, I restarted Apache and the bug came back, again only in IE we saw the chat slow down significantly and randomly disconnect.
Update 2 - SEEN IN OTHER BROWSERS
Today I was able to recreate the issue in other browsers (Chrome, Firefox) by opening multiple chat instances in other tabs. So it seems that IE only suffered worse from the issue - only needing one tab open. This is pointing me towards a browser concurrent connection limit issue, but that doesn't make sense to be either considering that I shouldn't be anywhere near the limit with 2 connections.
Update 3 - CAUSE DETERMINED IN OTHER BROWSERS
I performed a test in Firefox to confirm my suspicions that we are dealing with a concurrent connection issue. I opened one chat tab and the messages posted instantaneously. I opened a second one and, as expected, they delayed. I then opened about:config and changed network.http.max-persistent-connections-per-server from 6 to 7. After doing this I repeated the test. I was able to post messages instantaneously in both the first and second chat tabs, but when I opened a third they all began experiencing the delay. I'm going to try and test in IE to see if this is the same problem by modifying the FEATURE_MAXCONNECTIONSPERSERVER registry settings and seeing if the problem goes away.
Update 4 - IE ISSUE STILL NOT RESOLVED
I performed the same test in IE, changing the registry as shown here, adding iexplorer.exe DWORD settings to the FEATURE_MAXCONNECTIONSPERSERVER and FEATURE_MAXCONNECTIONSPER1_0SERVER registries set to 0xA, but no changes in behavior are apparent. I tried the same thing with the x64 settings (under Wow6432Node) and still observed no changes. I also tried changing the original explorer.exe values from 2 or 4 to 8, but still saw no changes in behavior, all after restarting the computer after each change.
Code
For reference, here is some of my XMPP chat code which may or may not be relevant:
XMPPAttach: function (jid, sid, rid) {
connection = new Strophe.Connection(BOSH_SERVICE);
connection.rawInput = function (data) {
log('RECV: ' + data);
};
connection.rawOutput = function (data) {
log('SENT: ' + data);
};
MY_JID = jid;
connection.addHandler(notifyUser, null, 'message', 'chat', null, null);
connection.addHandler(groupChat, null, 'message', 'groupchat', null, null);
connection.addHandler(presenceInfo, null, 'presence', null, null, null);
connection.ping.addPingHandler(pingHandler);
connection.attach(jid, sid, rid, onConnect, 300);
}
function onConnect(status) {
switch (status) {
case Strophe.Status.CONNECTED:
log('CONNECTED');
break;
case Strophe.Status.ERROR:
log('ERROR');
break;
case Strophe.Status.CONNFAIL:
log('CONNFAIL');
break;
case Strophe.Status.AUTHENTICATING:
log('AUTHENTICATING');
break;
case Strophe.Status.AUTHFAIL:
log('AUTHFAIL');
break;
case Strophe.Status.CONNECTING:
log('CONNECTING');
break;
case Strophe.Status.DISCONNECTED:
log('DISCONNECTED');
break;
case Strophe.Status.DISCONNECTING:
log('DISCONNECTING');
break;
case Strophe.Status.ATTACHED:
log('ATTACHED');
break;
default:
log('UKNOWN STATUS CODE');
break;
}
if ((status == Strophe.Status.CONNECTED || status == Strophe.Status.ATTACHED) && !presenceSent) {
connection.send($pres().tree());
presenceSent = true;
userLogin();
}
else if (status == Strophe.Status.CONNECTING || status == Strophe.Status.AUTHENTICATING) {
// do nothing
}
else if (status == Strophe.Status.AUTHFAIL) {
userInvalidLogin();
}
else {
userLoginFailed();
}
}
EnterChatRoom: function (room, nick) {
ROOM_JID = room;
MY_NICK = nick;
var chatJID = room.concat('/', nick);
var pres = $pres({ to: chatJID }).c('x', { xmlns: 'http://jabber.org/protocol/muc' });
connection.send(pres);
}
SendToRoom: function (text) {
var send = $msg({ to: ROOM_JID, type: 'groupchat' }).c('body', {}, text);
connection.send(send.tree());
},
And here is some of my XMPP messaging code:
function initializeXMPP() {
connection = new Strophe.Connection(BOSH_SERVICE);
intentionalDisconnect = false;
connection.rawInput = function (data) {
log('RECV: ' + data);
};
connection.rawOutput = function (data) {
log('SENT: ' + data);
};
connection.addHandler(onMessage, null, 'message', null, null, null);
connection.ping.addPingHandler(pingHandler);
connection.connect(messageCatcher.serverSettings.clientUser + '@' + messageCatcher.serverSettings.xmppDomain,
messageCatcher.serverSettings.clientUserPassword,
onConnect, 300, undefined, messageCatcher.serverSettings.route);
log('Strophe is connected.');
}
function onConnect(status) {
switch (status) {
case Strophe.Status.ERROR: // 0
log('ERROR');
StandardErrorHandler({ "Message": "XMPP Connection Error", "Status": "ERROR" });
break;
case Strophe.Status.CONNECTING: // 1
log('CONNECTING');
break;
case Strophe.Status.CONNFAIL: // 2
log('CONNFAIL');
StandardErrorHandler({ "Message": "XMPP Connection Error", "Status": "CONNFAIL" });
break;
case Strophe.Status.AUTHENTICATING: // 3
log('AUTHENTICATING');
break;
case Strophe.Status.AUTHFAIL: // 4
log('AUTHFAIL');
StandardErrorHandler("XMPP AUTHFAIL");
break;
case Strophe.Status.CONNECTED: // 5
log('CONNECTED');
callHandlers(connectHandlers);
break;
case Strophe.Status.DISCONNECTED: // 6
log('DISCONNECTED');
onDisconnect();
break;
case Strophe.Status.DISCONNECTING: // 7
log('DISCONNECTING');
break;
case Strophe.Status.ATTACHED: // 8
log('ATTACHED');
break;
default:
log('UKNOWN STATUS CODE');
break;
}
if (status == Strophe.Status.CONNECTED && !presenceSent) {
var pres = $pres({
//type: 'available'
});
connection.send(pres);
presenceSent = true;
log("PRESENCE SENT - SID: " + connection.sid);
}
}