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

feat: Enables stream resumption. #211

Merged
merged 2 commits into from
Dec 4, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 62 additions & 19 deletions jicoco/src/main/java/org/jitsi/xmpp/mucclient/MucClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@ public class MucClient

static
{
XMPPTCPConnection.setUseStreamManagementDefault(false);
XMPPTCPConnection.setUseStreamManagementResumptionDefault(false);
XMPPTCPConnection.setUseStreamManagementDefault(true);
XMPPTCPConnection.setUseStreamManagementResumptionDefault(true);
PingManager.setDefaultPingInterval(DEFAULT_PING_INTERVAL_SECONDS);
// We want to reconnect as soon as possible.
ReconnectionManager.setDefaultFixedDelay(1);
}

/**
Expand Down Expand Up @@ -155,8 +157,7 @@ public class MucClient
private AbstractXMPPConnection xmppConnection;

/**
* The connect loop: we keep this running forever and it re-establishes the
* connection in case it's broken.
* The retry we do on initial connect. After xmpp is connected the Smack reconnect kick-ins.
*/
private RetryStrategy connectRetry;

Expand Down Expand Up @@ -263,7 +264,7 @@ public MucClientConfiguration getConfig()
void start()
{
this.executor = ExecutorUtils.newScheduledThreadPool(1, true, MucClientManager.class.getSimpleName());
this.connectRetry = new RetryStrategy(this.executor);

this.executor.execute(() ->
{
try
Expand Down Expand Up @@ -310,28 +311,67 @@ private void initializeConnectAndJoin()
mucClientManager.getFeatures().forEach(sdm::addFeature);

ReconnectionManager reconnectionManager = ReconnectionManager.getInstanceFor(xmppConnection);
reconnectionManager.disableAutomaticReconnection();
reconnectionManager.enableAutomaticReconnection();

xmppConnection.addConnectionListener(new ConnectionListener()
{
@Override
public void connected(XMPPConnection xmppConnection)
{
mucClientManager.connected(MucClient.this);
logger.info("Connected.");

if (xmppConnection instanceof XMPPTCPConnection)
{
XMPPTCPConnection connection = (XMPPTCPConnection) xmppConnection;

logger.info("Connected. isSmEnabled:" + connection.isSmEnabled() +
" isSmAvailable:" + connection.isSmAvailable() +
" isSmResumptionPossible:" + connection.isSmResumptionPossible());
}
else
{
logger.info("Connected.");
}
}

@Override
public void authenticated(XMPPConnection xmppConnection, boolean b)
public void authenticated(XMPPConnection xmppConnection, boolean resumed)
{
logger.info("Authenticated, b=" + b);
logger.info("Authenticated, resumed=" + resumed);

if (!resumed)
{
try
{
joinMucs();
}
catch(Exception e)
{
logger.warn("Failed to join the MUCs.", e);
}
}
}

@Override
public void connectionClosed()
{
mucClientManager.closed(MucClient.this);
logger.info("Closed.");

if (MucClient.this.connectRetry != null)
{
// FIXME this is a workaround for an issue that can happen
// during a short network problem (~20 secs) where requests
// on the client side timeout during it and xmpp server
// tries to close the connection by sending </stream> which
// reaches the client when the network is back. That makes
// smack disconnect the connection and never retries
// if the connection was closed, we want to continue trying
// so we will trigger the reconnection logic again
// till we are connected and will relay on smack's reconnect
MucClient.this.connectRetry.runRetryingTask(
new SimpleRetryTask(0, 1000, true, getConnectAndLoginCallable()));
}
}

@Override
Expand All @@ -348,6 +388,7 @@ public void connectionClosedOnError(Exception e)
setIQListener(mucClientManager.getIqListener());

logger.info("Dispatching a thread to connect and login.");
this.connectRetry = new RetryStrategy(this.executor);
this.connectRetry.runRetryingTask(new SimpleRetryTask(0, 5000, true, getConnectAndLoginCallable()));
}

Expand Down Expand Up @@ -580,7 +621,11 @@ public String getId()
*/
void stop()
{
this.connectRetry.cancel();
if (this.connectRetry != null)
{
this.connectRetry.cancel();
this.connectRetry = null;
}

ReconnectionManager.getInstanceFor(xmppConnection).removeReconnectionListener(reconnectionListener);

Expand Down Expand Up @@ -662,15 +707,13 @@ private Callable<Boolean> getConnectAndLoginCallable()
return true;
}

try
{
joinMucs();
}
catch(Exception e)
{
logger.warn("Failed to join the MUCs.", e);
return true;
}
// The connection is successfully established, but we need to keep
// the executor alive, since it may be re-utilized by {@link #connectRetry}
// in case we ever need to restart the retry-connect-login logic.
// Essentially we need to keep the executor alive as long as we keep
// the {@link #connectRetry} alive.

return false;
}

return true;
Expand Down
Loading