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) {<br /> var pattern:RegExp = new RegExp("<flash:stream");<br /> var resultObj:Object = pattern.exec(ev.data);<br /> if (resultObj != null) // stop searching for unterminated node<br /> {<br /> ev.data = ev.data.concat("</flash:stream>");<br /> _expireTagSearch = true;<br /> } } */
if(ev.data.indexOf("<flash:stream") > -1) {<br /> ev.data += "</flash:stream>";<br /> } else if(ev.data.indexOf("<stream:stream") > -1) {<br /> ev.data += "</stream:stream>";<br /> } else if(ev.data.indexOf("</flash:stream>") > -1) {<br /> ev.data = "<flash:stream xmlns:flash=''http://www.jabber.com/streams/flash''>" + ev.data;<br /> <br /> } else if(ev.data.indexOf("</stream:stream>") > -1) {<br /> ev.data = "<stream:stream xmlns:flash=''http://etherx.jabber.org/streams''>" + ev.data;<br /> }
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 {<br /> // Create the socket<br /> socket = new XMLSocket();<br /> socket.addEventListener(Event.CONNECT,socketConnected);<br /> socket.addEventListener(IOErrorEvent.IO_ERROR,onIOError);<br /> socket.addEventListener(Event.CLOSE,socketClosed);<br /> socket.addEventListener(DataEvent.DATA,socketReceivedData);<br /> socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityError); <br /> }
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.
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("<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 = "<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) {<br /> ev.data += "</flash:stream>";<br /> } else if(ev.data.indexOf("<stream:stream") > -1) {<br /> ev.data += "</stream:stream>";<br /> } else if(ev.data.indexOf("</flash:stream>") > -1 || ev.data.indexOf("</stream:stream>") > -1) {<br /> return;<br /> }
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 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.