Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor reconnect plugin. #636

Merged
merged 6 commits into from Jan 17, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -20,6 +20,8 @@
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;

import java.util.*;

import static net.java.sip.communicator.plugin.reconnectplugin.ReconnectPluginActivator.*;

/**
Expand Down Expand Up @@ -53,6 +55,11 @@ public class PPReconnectWrapper
*/
private final Object localStateMutex = new Object();

/**
* Timer for scheduling the reconnect operation.
*/
private Timer timer = null;

/**
* Whether we had scheduled unregister for this provider.
*/
Expand All @@ -67,7 +74,7 @@ public class PPReconnectWrapper
/**
* The current reconnect task.
*/
private ReconnectPluginActivator.ReconnectTask currentReconnect = null;
private ReconnectTask currentReconnect = null;

/**
* Protects currentReconnect field.
Expand All @@ -82,6 +89,8 @@ public class PPReconnectWrapper
public PPReconnectWrapper(ProtocolProviderService provider)
{
this.provider = provider;
this.timer = new Timer("Reconnect timer p:"
+ provider.getAccountID().getAccountUniqueID(), true);

provider.addRegistrationStateChangeListener(this);
}
Expand All @@ -100,6 +109,12 @@ public ProtocolProviderService getProvider()
*/
public void clear()
{
if(timer != null)
{
timer.cancel();
timer = null;
}

this.provider.removeRegistrationStateChangeListener(this);

// if currently reconnecting cancel
Expand Down Expand Up @@ -166,7 +181,7 @@ public void registrationStateChanged(RegistrationStateChangeEvent evt)
{
if (state.equals(RegistrationState.REGISTERED))
{
ReconnectPluginActivator.addReconnectEnabledProvider(this);
addReconnectEnabledProvider(this);

// if currently reconnecting cancel
cancelReconnect();
Expand All @@ -179,12 +194,11 @@ public void registrationStateChanged(RegistrationStateChangeEvent evt)
else if (state.equals(RegistrationState.CONNECTION_FAILED)
&& !isServerReturnedErroneousInputEvent)
{
if (!ReconnectPluginActivator
.hasAtLeastOneSuccessfulConnection(pp))
if (!hasAtLeastOneSuccessfulConnection(pp))
{
// ignore providers which haven't registered successfully
// till now, they maybe miss-configured
ReconnectPluginActivator.notifyConnectionFailed(evt);
notifyConnectionFailed(evt);

return;
}
Expand All @@ -199,7 +213,7 @@ else if (state.equals(RegistrationState.CONNECTION_FAILED)
return;
}

if (ReconnectPluginActivator.anyConnectedInterfaces())
if (anyConnectedInterfaces())
{
// network is up but something happen and cannot reconnect
// strange lets try again after some time
Expand All @@ -216,8 +230,9 @@ else if (state.equals(RegistrationState.UNREGISTERED)
// event is by user request
if (evt.isUserRequest() || isServerReturnedErroneousInputEvent)
{
ReconnectPluginActivator
.removeReconnectEnabledProviders(this);
this.clear();

removeReconnectEnabledProviders(this);
}

// if currently reconnecting cancel
Expand Down Expand Up @@ -256,8 +271,8 @@ private void createReconnect(long delay)
{
if (this.currentReconnect == null)
{
this.currentReconnect = ReconnectPluginActivator
.scheduleReconnectIfNeeded(delay, this.provider);
this.currentReconnect
= scheduleReconnectIfNeeded(delay, this.provider);
}
else
{
Expand Down Expand Up @@ -358,4 +373,93 @@ public String toString()

return builder.toString();
}

/**
* Schedules a reconnect if needed (if there is timer and connected
* interfaces and user request is not null).
* @param delay The delay to use when creating the reconnect task.
* @param pp the protocol provider that will be reconnected.
*/
private ReconnectTask scheduleReconnectIfNeeded(
long delay, ProtocolProviderService pp)
{
final ReconnectTask task = new ReconnectTask();
task.delay = delay;

if (timer == null)
{
return null;
}

if (!anyConnectedInterfaces())
{
// There is no network, nothing to do, when
// network is back it will be scheduled to reconnect.
// This means we started unregistering while
// network was going down and meanwhile there
// were no connected interface, this happens
// when we have more than one connected
// interface and we got 2 events for down iface

return null;
}

if(logger.isInfoEnabled())
logger.info("Reconnect " + pp + " after " + task.delay + " ms.");

timer.schedule(task, task.delay);

return task;
}

/**
* The task executed by the timer when time for reconnect comes.
*/
private class ReconnectTask
extends TimerTask
{
/**
* The delay with which was this task scheduled.
*/
long delay;

/**
* The thread to execute this task.
*/
private Thread thread = null;

/**
* Reconnects the provider.
*/
@Override
public void run()
{
if(thread == null || !Thread.currentThread().equals(thread))
{
thread = new Thread(this);
paweldomas marked this conversation as resolved.
Show resolved Hide resolved
thread.start();
}
else
{
try
{
if (logger.isInfoEnabled())
logger.info("Start reconnecting " + provider);

provider.register(
getUIService().getDefaultSecurityAuthority(provider));
} catch (OperationFailedException ex)
{
logger.error("cannot re-register provider will keep going",
ex);
}
}
}

@Override
public String toString()
{
return super.toString() + "[delay=" + delay + "]";
}
}
}
Expand Up @@ -101,11 +101,6 @@ public class ReconnectPluginActivator
*/
private static final Set<String> connectedInterfaces = new HashSet<>();

/**
* Timer for scheduling all reconnect operations.
*/
private static Timer timer = null;

/**
* Start of the delay interval when starting a reconnect.
*/
Expand Down Expand Up @@ -169,9 +164,6 @@ public void start(BundleContext bundleContext)

bundleContext.addServiceListener(this);

if(timer == null)
timer = new Timer("Reconnect timer", true);

this.networkAddressManagerService
= ServiceUtils.getService(
bundleContext,
Expand Down Expand Up @@ -222,11 +214,6 @@ public void start(BundleContext bundleContext)
public void stop(BundleContext bundleContext)
throws Exception
{
if(timer != null)
{
timer.cancel();
timer = null;
}
}

/**
Expand Down Expand Up @@ -609,111 +596,6 @@ static void notifyConnectionFailed(RegistrationStateChangeEvent evt)
}
}

/**
* Schedules a reconnect if needed (if there is timer and connected
* interfaces and user request is not null).
* @param delay The delay to use when creating the reconnect task.
* @param pp the protocol provider that will be reconnected.
*/
static ReconnectTask scheduleReconnectIfNeeded(
long delay, ProtocolProviderService pp)
{
final ReconnectTask task = new ReconnectTask(pp);
task.delay = delay;

if (timer == null)
{
return null;
}

if (!anyConnectedInterfaces())
{
// There is no network, nothing to do, when
// network is back it will be scheduled to reconnect.
// This means we started unregistering while
// network was going down and meanwhile there
// were no connected interface, this happens
// when we have more than one connected
// interface and we got 2 events for down iface

return null;
}

if(logger.isInfoEnabled())
logger.info("Reconnect "
+ pp + " after " + task.delay + " ms.");

timer.schedule(task, task.delay);

return task;
}

/**
* The task executed by the timer when time for reconnect comes.
*/
static class ReconnectTask
extends TimerTask
{
/**
* The provider to reconnect.
*/
private ProtocolProviderService provider;

/**
* The delay with which was this task scheduled.
*/
long delay;

/**
* The thread to execute this task.
*/
private Thread thread = null;

/**
* Creates the task.
*
* @param provider the <tt>ProtocolProviderService</tt> to reconnect
*/
public ReconnectTask(ProtocolProviderService provider)
{
this.provider = provider;
}

/**
* Reconnects the provider.
*/
@Override
public void run()
{
if(thread == null || !Thread.currentThread().equals(thread))
{
thread = new Thread(this);
thread.start();
}
else
{
try
{
if (logger.isInfoEnabled())
logger.info("Start reconnecting " + provider);

provider.register(
getUIService().getDefaultSecurityAuthority(provider));
} catch (OperationFailedException ex)
{
logger.error("cannot re-register provider will keep going",
ex);
}
}
}

@Override
public String toString()
{
return super.toString() + "[delay=" + delay + "]";
}
}

/**
* Check does the supplied protocol has the property set for at least
* one successful connection.
Expand Down