Commit 87749f06 authored by Daniel Henninger's avatar Daniel Henninger Committed by dhenninger

[GATE-23] Lots of refactoring for good support of auto-reconnects.

However, currently very in progress.  Do -not- use.

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@8209 b35dd754-fafc-0310-a699-88a17e54d16e
parent bce27639
......@@ -20,23 +20,33 @@ package org.jivesoftware.openfire.gateway;
public enum TransportLoginStatus {
/**
* Not logged in
* Not logged in - not logged into the remote service at all
*/
LOGGED_OUT,
/**
* Currently logging in
* Currently logging in - in the process of logging into the remote service
*/
LOGGING_IN,
/**
* Logged in
* Logged in - active session that should be completely functional
*/
LOGGED_IN,
/**
* Logging out
* Logging out - in the process of logging out of the remote service
*/
LOGGING_OUT
LOGGING_OUT,
/**
* Disconnected - automatically disconnected for some reason, similar to LOGGED_OUT
*/
DISCONNECTED,
/**
* Reconnecting - in the process of automatically reconnecting, similar to LOGGING_IN
*/
RECONNECTING
}
......@@ -11,10 +11,14 @@
package org.jivesoftware.openfire.gateway;
import org.xmpp.packet.JID;
import org.xmpp.packet.Presence;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.openfire.roster.RosterItem;
import org.jivesoftware.openfire.roster.Roster;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.session.ClientSession;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.JiveGlobals;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
......@@ -111,6 +115,11 @@ public abstract class TransportSession implements Runnable {
*/
public ArrayList<SupportedFeature> supportedFeatures = new ArrayList<SupportedFeature>();
/**
* Number of reconnection attempts made.
*/
public Integer reconnectionAttempts = 0;
/**
* Associates a resource with the session, and tracks it's priority.
*
......@@ -379,6 +388,9 @@ public abstract class TransportSession implements Runnable {
*/
public void setLoginStatus(TransportLoginStatus status) {
loginStatus = status;
if (status.equals(TransportLoginStatus.LOGGED_IN)) {
reconnectionAttempts = 0;
}
}
/**
......@@ -413,6 +425,44 @@ public abstract class TransportSession implements Runnable {
validSession = false;
}
/**
* Should be called when a session has been disconnected.
*
* This can be anything from a standard logout to a forced disconnect from the server.
*/
public void sessionDisconnected() {
reconnectionAttempts++;
cleanUp();
if (reconnectionAttempts > JiveGlobals.getIntProperty("plugin.gateway."+getTransport().getType()+"reconnectattempts", 3)) {
sessionDisconnectedNoReconnect();
}
else {
setLoginStatus(TransportLoginStatus.RECONNECTING);
ClientSession session = XMPPServer.getInstance().getSessionManager().getSession(getJIDWithHighestPriority());
logIn(getTransport().getPresenceType(session.getPresence()), null);
}
}
/**
* Should be called when a session has been disconnected but no reconnect attempt should be made.
*
* It is also called internally by sessionDisconnected to handle total failed attempt.
*/
public void sessionDisconnectedNoReconnect() {
Log.debug("Disconnecting session "+getJID()+" from "+getTransport().getJID());
Presence p = new Presence(Presence.Type.unavailable);
p.setTo(getJID());
p.setFrom(getTransport().getJID());
getTransport().sendPacket(p);
setLoginStatus(TransportLoginStatus.LOGGED_OUT);
try {
getTransport().notifyRosterOffline(getJID());
}
catch (UserNotFoundException e) {
// Don't care
}
}
/**
* Updates status on legacy service.
*
......@@ -486,4 +536,26 @@ public abstract class TransportSession implements Runnable {
*/
public abstract void resendContactStatuses(JID jid);
/**
* Should be called when the service is to be logged into.
*
* This is expected to check for current logged in status and log in if appropriate.
*
* @param presenceType Initial status (away, available, etc) to be set upon logging in.
* @param verboseStatus Descriptive status to be set upon logging in.
*/
public abstract void logIn(PresenceType presenceType, String verboseStatus);
/**
* Should be called when the service is to be disconnected from.
*
* This is expected to check for current logged in status and log out if appropriate.
*/
public abstract void logOut();
/**
* Clean up session pieces for either a log out or in preparation for a reconnection.
*/
public abstract void cleanUp();
}
......@@ -38,7 +38,7 @@ public class IRCListener implements IRCEventListener {
/**
* Timer to check for online status.
*/
private Timer timer = new Timer();
public Timer timer = new Timer();
/**
* Interval at which status is checked.
......@@ -90,13 +90,7 @@ public class IRCListener implements IRCEventListener {
public void onDisconnected() {
Log.debug("IRC disconnected");
Presence p = new Presence(Presence.Type.unavailable);
p.setTo(getSession().getJID());
p.setFrom(getSession().getTransport().getJID());
getSession().getTransport().sendPacket(p);
getSession().getConnection().close();
timer.cancel();
getSession().setLoginStatus(TransportLoginStatus.LOGGED_OUT);
getSession().sessionDisconnected();
}
public void onError(String string) {
......@@ -192,12 +186,7 @@ public class IRCListener implements IRCEventListener {
public void onQuit(IRCUser ircUser, String string) {
Log.debug("IRC quit: "+ircUser+", "+string);
Presence p = new Presence(Presence.Type.unavailable);
p.setTo(getSession().getJID());
p.setFrom(getSession().getTransport().getJID());
getSession().getTransport().sendPacket(p);
getSession().getConnection().close();
getSession().setLoginStatus(TransportLoginStatus.LOGGED_OUT);
getSession().sessionDisconnectedNoReconnect();
}
public void onReply(int i, String string, String string1) {
......@@ -254,4 +243,8 @@ public class IRCListener implements IRCEventListener {
}
}
public Timer getTimer() {
return timer;
}
}
......@@ -94,9 +94,9 @@ public class IRCSession extends TransportSession {
* @param verboseStatus Initial full status information.
*/
public void logIn(PresenceType presenceType, String verboseStatus) {
setLoginStatus(TransportLoginStatus.LOGGED_IN);
try {
conn.connect();
setLoginStatus(TransportLoginStatus.LOGGED_IN);
}
catch (IOException e) {
Log.error("IO error while connecting to IRC: ", e);
......@@ -107,10 +107,16 @@ public class IRCSession extends TransportSession {
* Logs the session out of IRC.
*/
public void logOut() {
setLoginStatus(TransportLoginStatus.LOGGING_OUT);
ircListener.setSilenced(true);
conn.doQuit();
setLoginStatus(TransportLoginStatus.LOGGED_OUT);
if (isLoggedIn()) {
ircListener.setSilenced(true);
conn.doQuit();
sessionDisconnectedNoReconnect();
}
}
public void cleanUp() {
ircListener.getTimer().cancel();
conn.close();
}
/**
......
......@@ -11,7 +11,6 @@
package org.jivesoftware.openfire.gateway.protocols.irc;
import org.jivesoftware.openfire.gateway.*;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import org.xmpp.packet.JID;
......@@ -79,10 +78,9 @@ public class IRCTransport extends BaseTransport {
* @param verboseStatus Longer status description.
*/
public TransportSession registrationLoggedIn(Registration registration, JID jid, PresenceType presenceType, String verboseStatus, Integer priority) {
Log.debug("Logging in to IRC gateway.");
TransportSession session = new IRCSession(registration, jid, this, priority);
this.getSessionManager().startThread(session);
((IRCSession)session).logIn(presenceType, verboseStatus);
session.setLoginStatus(TransportLoginStatus.LOGGING_IN);
session.logIn(presenceType, verboseStatus);
return session;
}
......@@ -92,11 +90,8 @@ public class IRCTransport extends BaseTransport {
* @param session The session to be disconnected.
*/
public void registrationLoggedOut(TransportSession session) {
Log.debug("Logging out of IRC gateway.");
((IRCSession)session).logOut();
session.sessionDone();
// Just in case.
session.setLoginStatus(TransportLoginStatus.LOGGED_OUT);
session.setLoginStatus(TransportLoginStatus.LOGGING_OUT);
session.logOut();
}
/**
......
......@@ -284,7 +284,8 @@ public class MSNListener extends MsnAdapter {
LocaleUtils.getLocalizedString("gateway.msn.passwordincorrect", "gateway"),
Message.Type.error
);
msnSession.logOut();
msnSession.setLoginStatus(TransportLoginStatus.DISCONNECTED);
msnSession.sessionDisconnectedNoReconnect();
}
else if (throwable.getClass().getName().equals("net.sf.jml.exception.MsnProtocolException")) {
Log.debug("MSN: Protocol exception: "+throwable.toString());
......@@ -311,7 +312,8 @@ public class MSNListener extends MsnAdapter {
LocaleUtils.getLocalizedString("gateway.msn.disconnect", "gateway"),
Message.Type.error
);
msnSession.logOut();
msnSession.setLoginStatus(TransportLoginStatus.DISCONNECTED);
msnSession.sessionDisconnected();
}
else {
Log.debug("MSN: Unknown error: "+throwable.toString());
......
......@@ -93,10 +93,9 @@ public class MSNSession extends TransportSession {
* @param verboseStatus Long representation of status.
*/
public void logIn(PresenceType presenceType, String verboseStatus) {
if (!this.isLoggedIn()) {
if (!isLoggedIn()) {
try {
Log.debug("Logging in to MSN session for " + msnMessenger.getOwner().getEmail());
setLoginStatus(TransportLoginStatus.LOGGING_IN);
msnMessenger.getOwner().setInitStatus(((MSNTransport)getTransport()).convertJabStatusToMSN(presenceType));
msnMessenger.setLogIncoming(false);
msnMessenger.setLogOutgoing(false);
......@@ -115,15 +114,16 @@ public class MSNSession extends TransportSession {
* Log out of MSN.
*/
public void logOut() {
if (this.isLoggedIn()) {
setLoginStatus(TransportLoginStatus.LOGGING_OUT);
msnMessenger.logout();
}
Presence p = new Presence(Presence.Type.unavailable);
p.setTo(getJID());
p.setFrom(getTransport().getJID());
getTransport().sendPacket(p);
setLoginStatus(TransportLoginStatus.LOGGED_OUT);
Log.debug("Logging out of MSN");
if (isLoggedIn()) {
Log.debug("No really.");
cleanUp();
sessionDisconnectedNoReconnect();
}
}
public void cleanUp() {
msnMessenger.logout();
}
/**
......
......@@ -15,6 +15,7 @@ import net.sf.cindy.Session;
import net.sf.cindy.Message;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.openfire.gateway.TransportLoginStatus;
/**
* MSN Session Listener Interface.
......@@ -50,7 +51,8 @@ public class MSNSessionListener extends SessionAdapter {
LocaleUtils.getLocalizedString("gateway.msn.otherloggedin", "gateway"),
org.xmpp.packet.Message.Type.error
);
msnSession.logOut();
msnSession.setLoginStatus(TransportLoginStatus.DISCONNECTED);
msnSession.sessionDisconnectedNoReconnect();
}
else if (message.toString().startsWith("OUT SDH")) {
// Forced disconnect from server for maintenance
......@@ -60,7 +62,8 @@ public class MSNSessionListener extends SessionAdapter {
LocaleUtils.getLocalizedString("gateway.msn.disconnect", "gateway"),
org.xmpp.packet.Message.Type.error
);
msnSession.logOut();
msnSession.setLoginStatus(TransportLoginStatus.DISCONNECTED);
msnSession.sessionDisconnectedNoReconnect();
}
}
......
......@@ -10,7 +10,6 @@
package org.jivesoftware.openfire.gateway.protocols.msn;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.openfire.gateway.*;
import org.xmpp.packet.JID;
......@@ -81,10 +80,9 @@ public class MSNTransport extends BaseTransport {
* @param verboseStatus Longer status description.
*/
public TransportSession registrationLoggedIn(Registration registration, JID jid, PresenceType presenceType, String verboseStatus, Integer priority) {
Log.debug("Logging in to MSN gateway.");
TransportSession session = new MSNSession(registration, jid, this, priority);
this.getSessionManager().startThread(session);
((MSNSession)session).logIn(presenceType, verboseStatus);
session.setLoginStatus(TransportLoginStatus.LOGGING_IN);
session.logIn(presenceType, verboseStatus);
return session;
}
......@@ -94,11 +92,8 @@ public class MSNTransport extends BaseTransport {
* @param session The session to be disconnected.
*/
public void registrationLoggedOut(TransportSession session) {
Log.debug("Logging out of MSN gateway.");
((MSNSession)session).logOut();
session.sessionDone();
// Just in case.
session.setLoginStatus(TransportLoginStatus.LOGGED_OUT);
session.setLoginStatus(TransportLoginStatus.LOGGING_OUT);
session.logOut();
}
/**
......
......@@ -17,7 +17,6 @@ import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.openfire.gateway.TransportLoginStatus;
import org.jivesoftware.openfire.gateway.TransportType;
import org.xmpp.packet.Message;
import org.xmpp.packet.Presence;
import net.kano.joscar.*;
import net.kano.joscar.flap.*;
......@@ -66,8 +65,8 @@ public class LoginConnection extends BaseFlapConnection {
m.setFrom(this.getMainSession().getTransport().getJID());
m.setTo(this.getMainSession().getJIDWithHighestPriority());
m.setBody(LocaleUtils.getLocalizedString("gateway.oscar.connectionfailed", "gateway")+" " + e.getReason());
this.getMainSession().getTransport().sendPacket(m);
this.getMainSession().logOut();
getMainSession().getTransport().sendPacket(m);
getMainSession().sessionDisconnected();
}
else if (e.getNewState() == ClientFlapConn.STATE_NOT_CONNECTED) {
//TODO: Do we need to catch these?
......@@ -166,13 +165,7 @@ public class LoginConnection extends BaseFlapConnection {
m.setFrom(getMainSession().getTransport().getJID());
m.setBody(errormsg);
getMainSession().getTransport().sendPacket(m);
Presence p = new Presence();
p.setTo(getMainSession().getJID());
p.setFrom(getMainSession().getTransport().getJID());
p.setType(Presence.Type.unavailable);
getMainSession().getTransport().sendPacket(p);
getMainSession().setLoginStatus(TransportLoginStatus.LOGGED_OUT);
getMainSession().sessionDisconnectedNoReconnect();
}
else {
Log.debug("Got something else?");
......
......@@ -90,7 +90,6 @@ public class OSCARSession extends TransportSession {
public void logIn(PresenceType presenceType, String verboseStatus) {
if (!isLoggedIn()) {
setLoginStatus(TransportLoginStatus.LOGGING_IN);
loginConn = new LoginConnection(new ConnDescriptor(
JiveGlobals.getProperty(propertyPrefix+".connecthost", "login.oscar.aol.com"),
JiveGlobals.getIntProperty(propertyPrefix+".connectport", 5190)),
......@@ -107,40 +106,39 @@ public class OSCARSession extends TransportSession {
public synchronized void logOut() {
if (isLoggedIn()) {
setLoginStatus(TransportLoginStatus.LOGGING_OUT);
if (loginConn != null) {
loginConn.disconnect();
loginConn = null;
cleanUp();
sessionDisconnectedNoReconnect();
}
}
public synchronized void cleanUp() {
if (loginConn != null) {
loginConn.disconnect();
loginConn = null;
}
if (bosConn != null) {
bosConn.disconnect();
bosConn = null;
}
for (ServiceConnection conn : getServiceConnections()) {
try {
conn.disconnect();
}
if (bosConn != null) {
bosConn.disconnect();
bosConn = null;
catch (Exception e) {
// Ignore.
}
for (ServiceConnection conn : getServiceConnections()) {
try {
conn.disconnect();
}
catch (Exception e) {
// Ignore.
}
try {
services.remove(conn);
}
catch (Exception e) {
// Ignore.
}
try {
snacMgr.unregister(conn);
}
catch (Exception e) {
// Ignore.
}
try {
services.remove(conn);
}
catch (Exception e) {
// Ignore.
}
try {
snacMgr.unregister(conn);
}
catch (Exception e) {
// Ignore.
}
Presence p = new Presence(Presence.Type.unavailable);
p.setTo(getJID());
p.setFrom(getTransport().getJID());
getTransport().sendPacket(p);
setLoginStatus(TransportLoginStatus.LOGGED_OUT);
}
}
......@@ -424,7 +422,7 @@ public class OSCARSession extends TransportSession {
m.setFrom(getTransport().getJID());
m.setBody(LocaleUtils.getLocalizedString("gateway.oscar.disconnected", "gateway"));
getTransport().sendPacket(m);
logOut();
sessionDisconnected();
}
/**
......
......@@ -84,8 +84,8 @@ public class OSCARTransport extends BaseTransport {
*/
public TransportSession registrationLoggedIn(Registration registration, JID jid, PresenceType presenceType, String verboseStatus, Integer priority) {
TransportSession session = new OSCARSession(registration, jid, this, priority);
this.getSessionManager().startThread(session);
((OSCARSession)session).logIn(presenceType, verboseStatus);
session.setLoginStatus(TransportLoginStatus.LOGGING_IN);
session.logIn(presenceType, verboseStatus);
return session;
}
......@@ -95,10 +95,8 @@ public class OSCARTransport extends BaseTransport {
* @param session The session to be disconnected.
*/
public void registrationLoggedOut(TransportSession session) {
((OSCARSession)session).logOut();
session.sessionDone();
// Just in case.
session.setLoginStatus(TransportLoginStatus.LOGGED_OUT);
session.setLoginStatus(TransportLoginStatus.LOGGING_OUT);
session.logOut();
}
}
......@@ -77,8 +77,7 @@ public class XMPPSession extends TransportSession {
private JID acctjid = null;
public void logIn(PresenceType presenceType, String verboseStatus) {
if (!this.isLoggedIn()) {
setLoginStatus(TransportLoginStatus.LOGGING_IN);
if (!isLoggedIn()) {
new Thread() {
public void run() {
try {
......@@ -105,22 +104,18 @@ public class XMPPSession extends TransportSession {
}
}
/**
* Log out of MSN.
*/
public void logOut() {
if (this.isLoggedIn()) {
setLoginStatus(TransportLoginStatus.LOGGING_OUT);
conn.removeConnectionListener(listener);
conn.getRoster().removeRosterListener(listener);
conn.getChatManager().removeChatListener(listener);
conn.disconnect();
if (isLoggedIn()) {
cleanUp();
sessionDisconnectedNoReconnect();
}
Presence p = new Presence(Presence.Type.unavailable);
p.setTo(getJID());
p.setFrom(getTransport().getJID());
getTransport().sendPacket(p);
setLoginStatus(TransportLoginStatus.LOGGED_OUT);
}
public void cleanUp() {
conn.removeConnectionListener(listener);
conn.getRoster().removeRosterListener(listener);
conn.getChatManager().removeChatListener(listener);
conn.disconnect();
}
......
......@@ -84,8 +84,8 @@ public class XMPPTransport extends BaseTransport {
*/
public TransportSession registrationLoggedIn(Registration registration, JID jid, PresenceType presenceType, String verboseStatus, Integer priority) {
TransportSession session = new XMPPSession(registration, jid, this, priority);
this.getSessionManager().startThread(session);
((XMPPSession)session).logIn(presenceType, verboseStatus);
session.setLoginStatus(TransportLoginStatus.LOGGING_IN);
session.logIn(presenceType, verboseStatus);
return session;
}
......@@ -95,10 +95,8 @@ public class XMPPTransport extends BaseTransport {
* @param session The session to be disconnected.
*/
public void registrationLoggedOut(TransportSession session) {
((XMPPSession)session).logOut();
session.sessionDone();
// Just in case.
session.setLoginStatus(TransportLoginStatus.LOGGED_OUT);
session.setLoginStatus(TransportLoginStatus.LOGGING_OUT);
session.logOut();
}
}
......@@ -65,11 +65,6 @@ public class YahooSession extends TransportSession {
*/
private PseudoRoster pseudoRoster;
/**
* How many attempts have been made so far?
*/
private Integer loginAttempts = 0;
/**
* Yahoo session
*/
......@@ -95,12 +90,10 @@ public class YahooSession extends TransportSession {
this.presenceType = presenceType;
this.verboseStatus = verboseStatus;
final PresenceType pType = presenceType;
if (!isLoggedIn() && getLoginStatus() != TransportLoginStatus.LOGGING_IN && loginAttempts <= 3) {
setLoginStatus(TransportLoginStatus.LOGGING_IN);
if (!isLoggedIn()) {
new Thread() {
public void run() {
try {
loginAttempts++;
yahooSession.setStatus(Status.AVAILABLE);
yahooSession.login(registration.getUsername(), registration.getPassword());
setLoginStatus(TransportLoginStatus.LOGGED_IN);
......@@ -166,8 +159,13 @@ public class YahooSession extends TransportSession {
* Log out of Yahoo.
*/
public void logOut() {
setLoginStatus(TransportLoginStatus.LOGGED_OUT);
loginAttempts = 0;
if (isLoggedIn()) {
cleanUp();
sessionDisconnectedNoReconnect();
}
}
public void cleanUp() {
try {
yahooSession.logout();
}
......@@ -175,10 +173,6 @@ public class YahooSession extends TransportSession {
Log.debug("Failed to log out from Yahoo.");
}
yahooSession.reset();
Presence p = new Presence(Presence.Type.unavailable);
p.setTo(getJID());
p.setFrom(getTransport().getJID());
getTransport().sendPacket(p);
}
/**
......
......@@ -12,6 +12,7 @@ package org.jivesoftware.openfire.gateway.protocols.yahoo;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.openfire.gateway.TransportLoginStatus;
import org.xmpp.packet.Message;
import org.xmpp.packet.Presence;
import org.openymsg.network.YahooUser;
......@@ -150,7 +151,8 @@ public class YahooSessionListener implements SessionListener {
public void connectionClosed(SessionEvent event) {
Log.debug(event.toString());
if (yahooSession.isLoggedIn()) {
yahooSession.logOut();
yahooSession.setLoginStatus(TransportLoginStatus.DISCONNECTED);
yahooSession.sessionDisconnectedNoReconnect();
}
}
......
......@@ -10,7 +10,6 @@
package org.jivesoftware.openfire.gateway.protocols.yahoo;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.openfire.gateway.*;
import org.xmpp.packet.JID;
......@@ -81,10 +80,9 @@ public class YahooTransport extends BaseTransport {
* @param verboseStatus Longer status description.
*/
public TransportSession registrationLoggedIn(Registration registration, JID jid, PresenceType presenceType, String verboseStatus, Integer priority) {
Log.debug("Logging in to Yahoo gateway.");
TransportSession session = new YahooSession(registration, jid, this, priority);
this.getSessionManager().startThread(session);
((YahooSession)session).logIn(presenceType, verboseStatus);
session.setLoginStatus(TransportLoginStatus.LOGGING_IN);
session.logIn(presenceType, verboseStatus);
return session;
}
......@@ -94,11 +92,8 @@ public class YahooTransport extends BaseTransport {
* @param session The session to be disconnected.
*/
public void registrationLoggedOut(TransportSession session) {
Log.debug("Logging out of Yahoo gateway.");
((YahooSession)session).logOut();
session.sessionDone();
// Just in case.
session.setLoginStatus(TransportLoginStatus.LOGGED_OUT);
session.setLoginStatus(TransportLoginStatus.LOGGING_OUT);
session.logOut();
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment