Xiff 3 Beta Stream Closing Error

I’‘ve been noticing that if the server disconnects the xiff client (most likely for any reason, but in my particular case due to being idle), the socketReceivedData handler doesn’‘t seem to be able to process the </flash:stream> closing tag properly - and in fact there’'s nothing to even check for this that I can see. This causes an exception as soon as parseXML is called on that closing tag for some reason.

I know I must be missing why this was implemented this way, but I was curious if there is a fix in existence for this or if this is something I could contribute. Thanks!

I was able to fix the stream closing error by copying some code out of Daniel Dura’'s as3xmpp library (blog).

So, in addition to the stream closing error, I also noticed that if I attempted to re-connect to the server immediately after being disconnected nothing would happen. I haven’'t taken the time to nail down exactly what was occurring, but if I re-initialize the XMLSocket object and all the event handlers, it seemed to allow me to re-connect properly.

I’'m kind of surprised nobody has run into and/or fixed this already in the beta code.

Can you elaborate on what parts of the AS3xmpp code you copied to fix the socketReceivedData error? I am running into the exact same problem and would love to find a solution! Thanks.

-David

It would have been cool if I could have just attached the modified XMPPConnection class, but here’'s what I changed (new code is in blue):

line 493: protected function socketReceivedData( ev:DataEvent ):void


I commented out the Regular Expression search for the opening tag and added a straightforward search for opening/closing tags from the as3xmpp library:

        // parseXML is more strict in AS3 so we must check for the presence of flash:stream

// the unterminated tag should be in the first string of xml data retured from the server
/*
if (!_expireTagSearch) {

var pattern:RegExp = new RegExp("<flash:stream");

var resultObj:Object = pattern.exec(ev.data);

if (resultObj != null) // stop searching for unterminated node

{

ev.data = ev.data.concat("</flash:stream>");

_expireTagSearch = true;

}
}
*/

        if(ev.data.indexOf("&lt;flash:stream") &gt; -1)

{

ev.data += “</flash:stream>”;

}
else if(ev.data.indexOf("<stream:stream") > -1)
{

ev.data += “</stream:stream>”;

}
else if(ev.data.indexOf("</flash:stream>") > -1)
{

ev.data = “<flash:stream xmlns:flash=’‘http://www.jabber.com/streams/flash’’>” + ev.data;



}
else if(ev.data.indexOf("</stream:stream>") > -1)
{

ev.data = “<stream:stream xmlns:flash=’‘http://etherx.jabber.org/streams’’>” + ev.data;

}

This took care of handling closing the stream properly, but I also needed to re-connect to the server properly. I moved the socket initialization code in the constructor into it’'s own method:


    private function initializeSocket():void

{

// Create the socket

socket = new XMLSocket();

socket.addEventListener(Event.CONNECT,socketConnected);

socket.addEventListener(IOErrorEvent.IO_ERROR,onIOError);

socket.addEventListener(Event.CLOSE,socketClosed);

socket.addEventListener(DataEvent.DATA,socketReceivedData);

socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityError);

}

line 242: public function connect( streamType:String = “terminatedStandard” ):Boolean


I added two lines to the connect method, one to clear out any IQ packets from the old connection (may or may not be necessary) as well as initialize the socket.

active = false;

loggedIn = false;

        pendingIQs = new Object(); initializeSocket();

Obviously there could be some more thorough testing/optimization done to this code, but this seemed to fix my issues without any noticeable side effects.

file:///C:/Project%20Files/xiff/trunk/src/org/jivesoftware/xiff/core/XMPPConnect ion.as

why do we need <flash:stream />?

I’‘m not sure if I’‘m understanding what you’‘re asking exactly, but there isn’'t a check for a <flash:stream /> tag in the code I provided above.

Hmmm…

Looks like I’'m having the same problem too. Is the disconnect due to inactivity a setting within openfire?

I thought there was a setting preventing the server from ever booting a user and that I had that set. Doesn’'t seem to be working… hmmm…

-Walt

Hmm…

Just upgraded to the latest openfire and that seemed to solve the disconnect problems.

Never mind – still disconnects just takes longer to do so. It also no longer throws the old error.

I ran into an issue with the updated XMPPConnection code where occasionally when the server would send the stream closing tag, the XMPPConnection class would handle that tag as a stream initialization tag and send an authentication IQ packet back to the server before the server actually closed the socket. This caused an exception on the server side since it could not locate the associated session and occasionally an internal-server-error could be sent back to the client.

Here’'s the fix:


This code:

if(ev.data.indexOf("&lt;flash:stream") &gt; -1)

{

ev.data += “</flash:stream>”;

}
else if(ev.data.indexOf("<stream:stream") > -1)
{

ev.data += “</stream:stream>”;

}
else if(ev.data.indexOf("</flash:stream>") > -1)
{

ev.data = “<flash:stream xmlns:flash=’‘http://www.jabber.com/streams/flash’’>” + ev.data;

}
else if(ev.data.indexOf("</stream:stream>") > -1)
{

ev.data = “<stream:stream xmlns:flash=’‘http://etherx.jabber.org/streams’’>” + ev.data;

}

Should be changed to this code:
if(ev.data.indexOf("<flash:stream") > -1)
{

ev.data += “</flash:stream>”;

}
else if(ev.data.indexOf("<stream:stream") > -1)
{

ev.data += “</stream:stream>”;

}
else if(ev.data.indexOf("</flash:stream>") > -1 || ev.data.indexOf("</stream:stream>") > -1)
{

return;

}

I send keepAlive every minute to avoid disconnections

Yes, me too. I’ve put an idle timer reseted by actions (in/out), and when it reach 1 min, keep alive is sent.

I tested the Xiff 3.0 beta version by dropping the connections in OpenFire. Xiff detects that the connection is closed and correctly sends the disconnection event in the XmppConnection class. The problem is that the connection _active property is never set to false after sending the event (bug?). When my client sends a keepAlive message after the dropping of the connection, I get a socket error because the connection is already closed and the active flag is still set to true. My solution was to set the active property to false inside the XmppConnection.socketClosed function.

Alberto Acevedo