From 3252a2a77cefb4e64e32fc3203cf6987da17e849 Mon Sep 17 00:00:00 2001 From: Gaston Dombiak Date: Mon, 12 Jun 2006 16:32:18 +0000 Subject: [PATCH] keep alive final fixes. SMACK-141 git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@3972 b35dd754-fafc-0310-a699-88a17e54d16e --- .../org/jivesoftware/smack/PacketWriter.java | 72 +++++++++++++------ .../jivesoftware/smack/XMPPConnection.java | 3 + 2 files changed, 54 insertions(+), 21 deletions(-) diff --git a/source/org/jivesoftware/smack/PacketWriter.java b/source/org/jivesoftware/smack/PacketWriter.java index 76228753a..93cb37e68 100644 --- a/source/org/jivesoftware/smack/PacketWriter.java +++ b/source/org/jivesoftware/smack/PacketWriter.java @@ -41,18 +41,24 @@ class PacketWriter { private Thread writerThread; private Writer writer; private XMPPConnection connection; - private LinkedList queue; + final private LinkedList queue; private boolean done = false; - private List listeners = new ArrayList(); + final private List listeners = new ArrayList(); private boolean listenersDeleted = false; + /** + * Timestamp when the last stanza was sent to the server. This information is used + * by the keep alive process to only send heartbeats when the connection has been idle. + */ + private long lastActive = System.currentTimeMillis(); + /** * List of PacketInterceptor that will be notified when a new packet is about to be * sent to the server. These interceptors may modify the packet before it is being * actually sent to the server. */ - private List interceptors = new ArrayList(); + final private List interceptors = new ArrayList(); /** * Flag that indicates if an interceptor was deleted. This is an optimization flag. */ @@ -75,15 +81,6 @@ class PacketWriter { }; writerThread.setName("Smack Packet Writer"); writerThread.setDaemon(true); - - // Schedule a keep-alive task to run if the feature is enabled. will write - // out a space character each time it runs to keep the TCP/IP connection open. - int keepAliveInterval = SmackConfiguration.getKeepAliveInterval(); - if (keepAliveInterval > 0) { - Thread keepAliveThread = new Thread(new KeepAliveTask(keepAliveInterval)); - keepAliveThread.setDaemon(true); - keepAliveThread.start(); - } } /** @@ -198,6 +195,22 @@ class PacketWriter { writerThread.start(); } + /** + * Starts the keep alive process. A white space (aka heartbeat) is going to be + * sent to the server every 30 seconds (by default) since the last stanza was sent + * to the server. + */ + void startKeepAliveProcess() { + // Schedule a keep-alive task to run if the feature is enabled. will write + // out a space character each time it runs to keep the TCP/IP connection open. + int keepAliveInterval = SmackConfiguration.getKeepAliveInterval(); + if (keepAliveInterval > 0) { + Thread keepAliveThread = new Thread(new KeepAliveTask(keepAliveInterval)); + keepAliveThread.setDaemon(true); + keepAliveThread.start(); + } + } + void setWriter(Writer writer) { this.writer = writer; } @@ -221,7 +234,9 @@ class PacketWriter { try { queue.wait(2000); } - catch (InterruptedException ie) { } + catch (InterruptedException ie) { + // Do nothing + } } if (queue.size() > 0) { return (Packet)queue.removeLast(); @@ -243,6 +258,8 @@ class PacketWriter { synchronized (writer) { writer.write(packet.toXML()); writer.flush(); + // Keep track of the last time a stanza was sent to the server + lastActive = System.currentTimeMillis(); } } } @@ -251,12 +268,16 @@ class PacketWriter { writer.write(""); writer.flush(); } - catch (Exception e) { } + catch (Exception e) { + // Do nothing + } finally { try { writer.close(); } - catch (Exception e) { } + catch (Exception e) { + // Do nothing + } } } catch (IOException ioe){ @@ -440,20 +461,29 @@ class PacketWriter { // properly finish TLS negotiation and then start sending heartbeats. Thread.sleep(15000); } - catch (InterruptedException ie) { } + catch (InterruptedException ie) { + // Do nothing + } while (!done) { synchronized (writer) { - try { - writer.write(" "); - writer.flush(); + // Send heartbeat if no packet has been sent to the server for a given time + if (System.currentTimeMillis() - lastActive >= delay) { + try { + writer.write(" "); + writer.flush(); + } + catch (Exception e) { + // Do nothing + } } - catch (Exception e) { } } try { // Sleep until we should write the next keep-alive. Thread.sleep(delay); } - catch (InterruptedException ie) { } + catch (InterruptedException ie) { + // Do nothing + } } } } diff --git a/source/org/jivesoftware/smack/XMPPConnection.java b/source/org/jivesoftware/smack/XMPPConnection.java index 3999097e3..af90568e8 100644 --- a/source/org/jivesoftware/smack/XMPPConnection.java +++ b/source/org/jivesoftware/smack/XMPPConnection.java @@ -876,6 +876,9 @@ public class XMPPConnection { // Make note of the fact that we're now connected. connected = true; + // Start keep alive process (after TLS was negotiated - if available) + packetWriter.startKeepAliveProcess(); + // Notify that a new connection has been established connectionEstablished(this);