Behavior on network disconnect

Hello,

I am testing a chat client written using the XIFF API and I am seeing something which causes me concern. If I enter a room for the first time, I get a room join event and a subject change event containing the subject for the room. And if I leave the room and re-enter it, I get the same. But if I enter the room and then I get disconnected (e.g. a network problem or the user simply closes the browser the client is running in) before officially leaving the room, the server appears to continue to think I am in the room. And worse, this appears to cause a problem when I re-enter the room after re-launching the client … I don’‘t get any of the events (room join, subject change, etc.) … it is as if the server thinks I was already there so it doesn’'t send me any of the events. What is going on here? How is one to deal with the very real possibility that a client will get terminated abnormally or experience a network disconnect? I would have thought the server would have removed the user from any rooms they were in when they lose their connection to the server, but it certainly does not appear that this is the case? Any explanations, suggestions, or advice?

Bill Bailey

Can anyone at least confirm how this SHOULD work? I tried an experiment with the Spark client and it appears that if I terminate the Spark process without leaving the room, the client is still removed from the room when the client is disconnected. However, since I am terminating it through task manager, I’‘m not sure if the server is detecting the disconnect and removing the user or if the client is receiving a windows shutdown/terminate event and has a chance to leave the room and log off first. The only way I suppose to know for sure is to terminate the network connection while the client is still running, but this is a little more of an issue for me and I’‘d prefer not to go through that pain if it isn’'t necessary. Does anyone know how this is designed to work?

Bill

OK. This looks like a bug to me … unless there is some reason it has to work this way.

I just did an experiment where I logged in as user xyz and entered room testroom. I then logged in as admin and checked the current open sessions and current number of users in the room. User xyz showed up both as logged in and as being in the room. Then I abnormally terminated the client. The session for user xyz disappeared … SO it is pretty clear that the network connection was terminated and the server was able to detect it. However, user xyz still shows as being in testroom … even though he isn’'t even logged in any more! How can this be correct?

If I then log in as another user and enter testroom, user xyz shows up on the roster as if he/she were in the room. But he/she isn’'t even logged into the server.

And as stated in the first posting, if user xyz tries to reenter the room, the client does not receive the right sequence of messages (apparently because the server believed the user was ALREADY in the room).

Is there not anyone out there who can comment on this?

Thanks.

Bill

FYI. If I change the global room settings to kick users after being idle for N minutes, the user is eventually removed from the room after the timeout expires. But this isn’‘t really appropriate for me because a) it is perfectly legitimate for users to be in the room for long periods of time without actually saying anything and b) if I set the timeout period for a long period of time, then I am effectively in the same situation as I am in if I don’‘t kick the users at all … i.e. if the user gets disconnected abnormally they won’'t be able to reenter the room for a long time.

Help? Anyone?

Bill

Hi again,

Not sure why I’'m posting this given my past lack of success, but here goes …

I have found that if I forcibly leave the room before I join it each time, it fixes the problem. If the user was left in the room from a previous disconnect, they are removed and then they are re-added. So far I don’‘t see any problem in this approach. Even if the user is not in the room, the leave room message doesn’'t seem to cause a problem. But as always, I am uneasy doing something that seems to me to be a hack. I still maintain that the server should be able to remove the user when the user is disconnected … as I mentioned in a previous entry, the server obviously recognizes that the user was disconnected because the user session disappears from the list of active sessions.

Anybody have anything to say about this?

Bill

i wish i had something constructive to assist you with, but i wanted to say that i agree with your statements. it is an issue for me as well.

i was thinking that i’'d have to edit the openfire source to fix this (when the server recognizes the disconnect, lookup the users presence and leave any rooms)

i haven’‘t gotten to that task yet, but i’‘ve been following your thread to see how you’'ve been handling it.

Just FYI for those who may be having the same problem. For now, my solution is to a) add a javascript handler to the page hosting my application to trap the beforeunload event on the window and execute the leave() method on the room using the ExternalInterface (this only catches the more common case where the user closes the window or navigates to another page … doesn’‘t address an abnormal exit or network disconnect) and b) I always leave the room before entering it even if I don’‘t think I should be need to … it’‘s a hack and I don’‘t like it, but it is working. One thing I have not verified yet with this latter approach is what happens if my client is running on one machine when entering the room the first time and another machine when it tries to re-enter the room later. That is, I don’'t know what criteria must be met before OpenFire will boot a user from the room based on a leave message … it seems reasonable that at least the JID of both users must be the same, but what about something like IP address? If I have enough time I may test this scenario later to make sure my solution works in the more general case.

At any rate, it doesn’'t look like I am going to get any response in the freebie forums so we have decided to buy just enough licenses to make the $2500 cutoff so we can get Standard (phone, email, chat) support. I plan to pursue this further once I can get an actual human on the line. I will update the thread again when and if I get resolution on this issue. Stay tuned

Bill.

good to hear.

i’'m going to investigate if its possible to write a plugin to detect the socket disconnection and kick the user from any rooms they are in.

bill, try compiling this code as a plugin and see if it works for you.

package org.example;

import org.jivesoftware.openfire.container.Plugin;

import org.jivesoftware.openfire.container.PluginManager;

import org.jivesoftware.openfire.XMPPServer;

import org.jivesoftware.openfire.event.SessionEventDispatcher;

import org.jivesoftware.openfire.event.SessionEventListener;

import org.jivesoftware.openfire.session.Session;

import org.jivesoftware.openfire.muc.MultiUserChatServer;

import org.xmpp.packet.JID;

import java.io.File;

/**

  • Detects session disconnects and kicks users from MUC chat rooms.

*/

public class DisconnectLeaveRoom implements Plugin, SessionEventListener {

private MultiUserChatServer mucs;

public void initializePlugin(PluginManager manager, File pluginDirectory) {

mucs = XMPPServer.getInstance().getMultiUserChatServer();

SessionEventDispatcher.addListener(this);

}

public void destroyPlugin() {

SessionEventDispatcher.removeListener(this);

mucs = null;

}

public void anonymousSessionCreated(Session session) {

}

public void anonymousSessionDestroyed(Session session) {

// when an anon session is lost, clean up any rooms they were in

JID jid = session.getAddress();

mucs.removeUser(jid);

}

public void sessionCreated(Session session) {

}

public void sessionDestroyed(Session session) {

}

}

Thanks. I will give this try some time today and let you know how it worked.

Bill

Just curious. Is there a reason you only handle this in the anonymous session case? In my case, every user will have a registered username so none of the sessions will be anonymous. Therefore, I think I need to handle this situation in the sessionDestroyed() method as well. Did you only implement the anonymous method just because all your users are anonymous sessions OR did you try it in the other method and run into some problem?

Thanks.

Bill

It looks like it is working. Of course, it will need more testing to verify that it works in scenarios where the user is in more than one room when they are disconnected (only tested the simple case where they are in a single room) and to verify that there are not any other ill side-effects. The code seems simple enough so its hard to imagine it would break anything, but there is a lot of code in this beast that I’'m not familiar with so who knows.

Thanks for your help. I think I will still file a bug once I have access to the support folks since I think this really should be part of the base functionality, but at least this gets me past one more hurdle.

Bill

yes, i did anon only due to my requirements. copying that code to the other method should work for you.

the method i use (removeUser) removes that JID from all chat rooms they are in.