mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-22 22:32:06 +01:00
Only send scheduled Pings if no Pong was received
in the meantime. Also do not distinguish between successful automatic and manual Ping. Just record the time of the last received XMPP Pong.
This commit is contained in:
parent
854489e785
commit
656b1c70be
1 changed files with 45 additions and 30 deletions
|
@ -65,6 +65,8 @@ public class PingManager extends Manager {
|
||||||
|
|
||||||
private static final PacketFilter PING_PACKET_FILTER = new AndFilter(
|
private static final PacketFilter PING_PACKET_FILTER = new AndFilter(
|
||||||
new PacketTypeFilter(Ping.class), new IQTypeFilter(Type.GET));
|
new PacketTypeFilter(Ping.class), new IQTypeFilter(Type.GET));
|
||||||
|
private static final PacketFilter PONG_PACKET_FILTER = new AndFilter(new PacketTypeFilter(
|
||||||
|
Pong.class), new IQTypeFilter(Type.RESULT));
|
||||||
|
|
||||||
static {
|
static {
|
||||||
XMPPConnection.addConnectionCreationListener(new ConnectionCreationListener() {
|
XMPPConnection.addConnectionCreationListener(new ConnectionCreationListener() {
|
||||||
|
@ -109,17 +111,12 @@ public class PingManager extends Manager {
|
||||||
*/
|
*/
|
||||||
private int pingInterval = defaultPingInterval;
|
private int pingInterval = defaultPingInterval;
|
||||||
|
|
||||||
/**
|
|
||||||
* The time in milliseconds the last successful ping was send to the users server.
|
|
||||||
*/
|
|
||||||
private volatile long lastSuccessfulAutomaticPing = -1;
|
|
||||||
|
|
||||||
private ScheduledFuture<?> nextAutomaticPing;
|
private ScheduledFuture<?> nextAutomaticPing;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The time in milliseconds the last manual ping as successful.
|
* The time in milliseconds the last pong was received.
|
||||||
*/
|
*/
|
||||||
private long lastSuccessfulManualPing = -1;
|
private long lastPongReceived = -1;
|
||||||
|
|
||||||
private PingManager(XMPPConnection connection) {
|
private PingManager(XMPPConnection connection) {
|
||||||
super(connection);
|
super(connection);
|
||||||
|
@ -135,6 +132,12 @@ public class PingManager extends Manager {
|
||||||
connection().sendPacket(pong);
|
connection().sendPacket(pong);
|
||||||
}
|
}
|
||||||
}, PING_PACKET_FILTER);
|
}, PING_PACKET_FILTER);
|
||||||
|
connection.addPacketListener(new PacketListener() {
|
||||||
|
@Override
|
||||||
|
public void processPacket(Packet packet) throws NotConnectedException {
|
||||||
|
lastPongReceived = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
}, PONG_PACKET_FILTER);
|
||||||
connection.addConnectionListener(new AbstractConnectionListener() {
|
connection.addConnectionListener(new AbstractConnectionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void authenticated(XMPPConnection connection) {
|
public void authenticated(XMPPConnection connection) {
|
||||||
|
@ -163,10 +166,10 @@ public class PingManager extends Manager {
|
||||||
* @param jid The id of the entity the ping is being sent to
|
* @param jid The id of the entity the ping is being sent to
|
||||||
* @param pingTimeout The time to wait for a reply
|
* @param pingTimeout The time to wait for a reply
|
||||||
* @return true if a reply was received from the entity, false otherwise.
|
* @return true if a reply was received from the entity, false otherwise.
|
||||||
* @throws NoResponseException if there was no response from the server.
|
* @throws NoResponseException if there was no response from the jid.
|
||||||
* @throws NotConnectedException
|
* @throws NotConnectedException
|
||||||
*/
|
*/
|
||||||
public boolean ping(String jid, long pingTimeout) throws NoResponseException, NotConnectedException {
|
public boolean ping(String jid, long pingTimeout) throws NotConnectedException, NoResponseException {
|
||||||
Ping ping = new Ping(jid);
|
Ping ping = new Ping(jid);
|
||||||
try {
|
try {
|
||||||
connection().createPacketCollectorAndSend(ping).nextResultOrThrow();
|
connection().createPacketCollectorAndSend(ping).nextResultOrThrow();
|
||||||
|
@ -184,9 +187,9 @@ public class PingManager extends Manager {
|
||||||
* @param jid The id of the entity the ping is being sent to
|
* @param jid The id of the entity the ping is being sent to
|
||||||
* @return true if a reply was received from the entity, false otherwise.
|
* @return true if a reply was received from the entity, false otherwise.
|
||||||
* @throws NotConnectedException
|
* @throws NotConnectedException
|
||||||
* @throws NoResponseException
|
* @throws NoResponseException if there was no response from the jid.
|
||||||
*/
|
*/
|
||||||
public boolean ping(String jid) throws NoResponseException, NotConnectedException {
|
public boolean ping(String jid) throws NotConnectedException, NoResponseException {
|
||||||
return ping(jid, connection().getPacketReplyTimeout());
|
return ping(jid, connection().getPacketReplyTimeout());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,7 +199,7 @@ public class PingManager extends Manager {
|
||||||
* @param jid The id of the entity the query is being sent to
|
* @param jid The id of the entity the query is being sent to
|
||||||
* @return true if it supports ping, false otherwise.
|
* @return true if it supports ping, false otherwise.
|
||||||
* @throws XMPPErrorException An XMPP related error occurred during the request
|
* @throws XMPPErrorException An XMPP related error occurred during the request
|
||||||
* @throws NoResponseException if there was no response from the server.
|
* @throws NoResponseException if there was no response from the jid.
|
||||||
* @throws NotConnectedException
|
* @throws NotConnectedException
|
||||||
*/
|
*/
|
||||||
public boolean isPingSupported(String jid) throws NoResponseException, XMPPErrorException, NotConnectedException {
|
public boolean isPingSupported(String jid) throws NoResponseException, XMPPErrorException, NotConnectedException {
|
||||||
|
@ -236,11 +239,7 @@ public class PingManager extends Manager {
|
||||||
catch (NoResponseException e) {
|
catch (NoResponseException e) {
|
||||||
res = false;
|
res = false;
|
||||||
}
|
}
|
||||||
|
if (!res && notifyListeners) {
|
||||||
if (res) {
|
|
||||||
pongReceived();
|
|
||||||
}
|
|
||||||
else if (notifyListeners) {
|
|
||||||
for (PingFailedListener l : pingFailedListeners)
|
for (PingFailedListener l : pingFailedListeners)
|
||||||
l.pingFailed();
|
l.pingFailed();
|
||||||
}
|
}
|
||||||
|
@ -285,24 +284,30 @@ public class PingManager extends Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the time of the last successful Ping with the
|
* Returns the timestamp when the last XMPP Pong was received.
|
||||||
* users server. If there was no successful Ping (e.g. because this
|
|
||||||
* feature is disabled) -1 will be returned.
|
|
||||||
*
|
*
|
||||||
* @return the timestamp of the last successful ping.
|
* @return the timestamp of the last XMPP Pong
|
||||||
*/
|
*/
|
||||||
public long getLastSuccessfulPing() {
|
public long getLastReceivedPong() {
|
||||||
return Math.max(lastSuccessfulAutomaticPing, lastSuccessfulManualPing);
|
return lastPongReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void maybeSchedulePingServerTask() {
|
||||||
|
maybeSchedulePingServerTask(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancels any existing periodic ping task if there is one and schedules a new ping task if
|
* Cancels any existing periodic ping task if there is one and schedules a new ping task if
|
||||||
* pingInterval is greater then zero.
|
* pingInterval is greater then zero.
|
||||||
|
*
|
||||||
|
* @param delta the delta to the last received ping in seconds
|
||||||
*/
|
*/
|
||||||
private synchronized void maybeSchedulePingServerTask() {
|
private synchronized void maybeSchedulePingServerTask(int delta) {
|
||||||
maybeStopPingServerTask();
|
maybeStopPingServerTask();
|
||||||
if (pingInterval > 0) {
|
if (pingInterval > 0) {
|
||||||
LOGGER.fine("Scheduling ServerPingTask in " + pingInterval + " seconds");
|
int nextPingIn = pingInterval - delta;
|
||||||
|
LOGGER.fine("Scheduling ServerPingTask in " + nextPingIn + " seconds (pingInterval="
|
||||||
|
+ pingInterval + ", delta=" + delta + ")");
|
||||||
nextAutomaticPing = connection().schedule(pingServerRunnable, pingInterval, TimeUnit.SECONDS);
|
nextAutomaticPing = connection().schedule(pingServerRunnable, pingInterval, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -314,10 +319,6 @@ public class PingManager extends Manager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pongReceived() {
|
|
||||||
lastSuccessfulManualPing = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Runnable pingServerRunnable = new Runnable() {
|
private final Runnable pingServerRunnable = new Runnable() {
|
||||||
private static final int DELTA = 1000; // 1 seconds
|
private static final int DELTA = 1000; // 1 seconds
|
||||||
private static final int TRIES = 3; // 3 tries
|
private static final int TRIES = 3; // 3 tries
|
||||||
|
@ -330,6 +331,21 @@ public class PingManager extends Manager {
|
||||||
// which means we can stop the thread by breaking the loop
|
// which means we can stop the thread by breaking the loop
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (pingInterval <= 0) {
|
||||||
|
// Ping has been disabled
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
long lastReceivedPong = getLastReceivedPong();
|
||||||
|
if (lastReceivedPong > 0) {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
// Calculate the delta from now to the next ping time. If delta is positive, the
|
||||||
|
// last successful ping was not to long ago, so we can defer the current ping.
|
||||||
|
int delta = (int) (((pingInterval * 1000) - (now - lastReceivedPong)) / 1000);
|
||||||
|
if (delta > 0) {
|
||||||
|
maybeSchedulePingServerTask(delta);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (connection.isAuthenticated()) {
|
if (connection.isAuthenticated()) {
|
||||||
boolean res = false;
|
boolean res = false;
|
||||||
|
|
||||||
|
@ -352,7 +368,6 @@ public class PingManager extends Manager {
|
||||||
}
|
}
|
||||||
// stop when we receive a pong back
|
// stop when we receive a pong back
|
||||||
if (res) {
|
if (res) {
|
||||||
lastSuccessfulAutomaticPing = System.currentTimeMillis();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue