Add dedicated listener manager.
[jFCPlib.git] / src / net / pterodactylus / fcp / FcpConnection.java
index 5757d61..05d8815 100644 (file)
@@ -36,9 +36,8 @@ import java.util.logging.Logger;
 
 /**
  * An FCP connection to a Freenet node.
- *
+ * 
  * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
- * @version $Id$
  */
 public class FcpConnection implements Closeable {
 
@@ -75,7 +74,7 @@ public class FcpConnection implements Closeable {
        /**
         * Creates a new FCP connection to the freenet node running on localhost,
         * using the default port.
-        *
+        * 
         * @throws UnknownHostException
         *             if the hostname can not be resolved
         */
@@ -86,7 +85,7 @@ public class FcpConnection implements Closeable {
        /**
         * Creates a new FCP connection to the Freenet node running on the given
         * host, listening on the default port.
-        *
+        * 
         * @param host
         *            The hostname of the Freenet node
         * @throws UnknownHostException
@@ -99,7 +98,7 @@ public class FcpConnection implements Closeable {
        /**
         * Creates a new FCP connection to the Freenet node running on the given
         * host, listening on the given port.
-        *
+        * 
         * @param host
         *            The hostname of the Freenet node
         * @param port
@@ -114,7 +113,7 @@ public class FcpConnection implements Closeable {
        /**
         * Creates a new FCP connection to the Freenet node running at the given
         * address, listening on the default port.
-        *
+        * 
         * @param address
         *            The address of the Freenet node
         */
@@ -125,7 +124,7 @@ public class FcpConnection implements Closeable {
        /**
         * Creates a new FCP connection to the Freenet node running at the given
         * address, listening on the given port.
-        *
+        * 
         * @param address
         *            The address of the Freenet node
         * @param port
@@ -142,7 +141,7 @@ public class FcpConnection implements Closeable {
 
        /**
         * Adds the given listener to the list of listeners.
-        *
+        * 
         * @param fcpListener
         *            The listener to add
         */
@@ -152,7 +151,7 @@ public class FcpConnection implements Closeable {
 
        /**
         * Removes the given listener from the list of listeners.
-        *
+        * 
         * @param fcpListener
         *            The listener to remove
         */
@@ -162,13 +161,13 @@ public class FcpConnection implements Closeable {
 
        /**
         * Notifies listeners that a “NodeHello” message was received.
-        *
+        * 
         * @see FcpListener#receivedNodeHello(FcpConnection, NodeHello)
         * @param nodeHello
         *            The “NodeHello” message
         */
        private void fireReceivedNodeHello(NodeHello nodeHello) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedNodeHello(this, nodeHello);
                }
        }
@@ -176,157 +175,157 @@ public class FcpConnection implements Closeable {
        /**
         * Notifies listeners that a “CloseConnectionDuplicateClientName” message
         * was received.
-        *
+        * 
         * @see FcpListener#receivedCloseConnectionDuplicateClientName(FcpConnection,
         *      CloseConnectionDuplicateClientName)
         * @param closeConnectionDuplicateClientName
         *            The “CloseConnectionDuplicateClientName” message
         */
        private void fireReceivedCloseConnectionDuplicateClientName(CloseConnectionDuplicateClientName closeConnectionDuplicateClientName) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedCloseConnectionDuplicateClientName(this, closeConnectionDuplicateClientName);
                }
        }
 
        /**
         * Notifies listeners that a “SSKKeypair” message was received.
-        *
+        * 
         * @see FcpListener#receivedSSKKeypair(FcpConnection, SSKKeypair)
         * @param sskKeypair
         *            The “SSKKeypair” message
         */
        private void fireReceivedSSKKeypair(SSKKeypair sskKeypair) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedSSKKeypair(this, sskKeypair);
                }
        }
 
        /**
         * Notifies listeners that a “Peer” message was received.
-        *
+        * 
         * @see FcpListener#receivedPeer(FcpConnection, Peer)
         * @param peer
         *            The “Peer” message
         */
        private void fireReceivedPeer(Peer peer) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedPeer(this, peer);
                }
        }
 
        /**
         * Notifies all listeners that an “EndListPeers” message was received.
-        *
+        * 
         * @see FcpListener#receivedEndListPeers(FcpConnection, EndListPeers)
         * @param endListPeers
         *            The “EndListPeers” message
         */
        private void fireReceivedEndListPeers(EndListPeers endListPeers) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedEndListPeers(this, endListPeers);
                }
        }
 
        /**
         * Notifies all listeners that a “PeerNote” message was received.
-        *
+        * 
         * @see FcpListener#receivedPeerNote(FcpConnection, PeerNote)
         * @param peerNote
         */
        private void fireReceivedPeerNote(PeerNote peerNote) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedPeerNote(this, peerNote);
                }
        }
 
        /**
         * Notifies all listeners that an “EndListPeerNotes” message was received.
-        *
+        * 
         * @see FcpListener#receivedEndListPeerNotes(FcpConnection,
         *      EndListPeerNotes)
         * @param endListPeerNotes
         *            The “EndListPeerNotes” message
         */
        private void fireReceivedEndListPeerNotes(EndListPeerNotes endListPeerNotes) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedEndListPeerNotes(this, endListPeerNotes);
                }
        }
 
        /**
         * Notifies all listeners that a “PeerRemoved” message was received.
-        *
+        * 
         * @see FcpListener#receivedPeerRemoved(FcpConnection, PeerRemoved)
         * @param peerRemoved
         *            The “PeerRemoved” message
         */
        private void fireReceivedPeerRemoved(PeerRemoved peerRemoved) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedPeerRemoved(this, peerRemoved);
                }
        }
 
        /**
         * Notifies all listeners that a “NodeData” message was received.
-        *
+        * 
         * @see FcpListener#receivedNodeData(FcpConnection, NodeData)
         * @param nodeData
         *            The “NodeData” message
         */
        private void fireReceivedNodeData(NodeData nodeData) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedNodeData(this, nodeData);
                }
        }
 
        /**
         * Notifies all listeners that a “TestDDAReply” message was received.
-        *
+        * 
         * @see FcpListener#receivedTestDDAReply(FcpConnection, TestDDAReply)
         * @param testDDAReply
         *            The “TestDDAReply” message
         */
        private void fireReceivedTestDDAReply(TestDDAReply testDDAReply) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedTestDDAReply(this, testDDAReply);
                }
        }
 
        /**
         * Notifies all listeners that a “TestDDAComplete” message was received.
-        *
+        * 
         * @see FcpListener#receivedTestDDAComplete(FcpConnection, TestDDAComplete)
         * @param testDDAComplete
         *            The “TestDDAComplete” message
         */
        private void fireReceivedTestDDAComplete(TestDDAComplete testDDAComplete) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedTestDDAComplete(this, testDDAComplete);
                }
        }
 
        /**
         * Notifies all listeners that a “PersistentGet” message was received.
-        *
+        * 
         * @see FcpListener#receivedPersistentGet(FcpConnection, PersistentGet)
         * @param persistentGet
         *            The “PersistentGet” message
         */
        private void fireReceivedPersistentGet(PersistentGet persistentGet) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedPersistentGet(this, persistentGet);
                }
        }
 
        /**
         * Notifies all listeners that a “PersistentPut” message was received.
-        *
+        * 
         * @see FcpListener#receivedPersistentPut(FcpConnection, PersistentPut)
         * @param persistentPut
         *            The “PersistentPut” message
         */
        private void fireReceivedPersistentPut(PersistentPut persistentPut) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedPersistentPut(this, persistentPut);
                }
        }
@@ -334,94 +333,94 @@ public class FcpConnection implements Closeable {
        /**
         * Notifies all listeners that a “EndListPersistentRequests” message was
         * received.
-        *
+        * 
         * @see FcpListener#receivedEndListPersistentRequests(FcpConnection,
         *      EndListPersistentRequests)
         * @param endListPersistentRequests
         *            The “EndListPersistentRequests” message
         */
        private void fireReceivedEndListPersistentRequests(EndListPersistentRequests endListPersistentRequests) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedEndListPersistentRequests(this, endListPersistentRequests);
                }
        }
 
        /**
         * Notifies all listeners that a “URIGenerated” message was received.
-        *
+        * 
         * @see FcpListener#receivedURIGenerated(FcpConnection, URIGenerated)
         * @param uriGenerated
         *            The “URIGenerated” message
         */
        private void fireReceivedURIGenerated(URIGenerated uriGenerated) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedURIGenerated(this, uriGenerated);
                }
        }
 
        /**
         * Notifies all listeners that a “DataFound” message was received.
-        *
+        * 
         * @see FcpListener#receivedDataFound(FcpConnection, DataFound)
         * @param dataFound
         *            The “DataFound” message
         */
        private void fireReceivedDataFound(DataFound dataFound) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedDataFound(this, dataFound);
                }
        }
 
        /**
         * Notifies all listeners that an “AllData” message was received.
-        *
+        * 
         * @see FcpListener#receivedAllData(FcpConnection, AllData)
         * @param allData
         *            The “AllData” message
         */
        private void fireReceivedAllData(AllData allData) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedAllData(this, allData);
                }
        }
 
        /**
         * Notifies all listeners that a “SimpleProgress” message was received.
-        *
+        * 
         * @see FcpListener#receivedSimpleProgress(FcpConnection, SimpleProgress)
         * @param simpleProgress
         *            The “SimpleProgress” message
         */
        private void fireReceivedSimpleProgress(SimpleProgress simpleProgress) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedSimpleProgress(this, simpleProgress);
                }
        }
 
        /**
         * Notifies all listeners that a “StartedCompression” message was received.
-        *
+        * 
         * @see FcpListener#receivedStartedCompression(FcpConnection,
         *      StartedCompression)
         * @param startedCompression
         *            The “StartedCompression” message
         */
        private void fireReceivedStartedCompression(StartedCompression startedCompression) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedStartedCompression(this, startedCompression);
                }
        }
 
        /**
         * Notifies all listeners that a “FinishedCompression” message was received.
-        *
+        * 
         * @see FcpListener#receviedFinishedCompression(FcpConnection,
         *      FinishedCompression)
         * @param finishedCompression
         *            The “FinishedCompression” message
         */
        private void fireReceivedFinishedCompression(FinishedCompression finishedCompression) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receviedFinishedCompression(this, finishedCompression);
                }
        }
@@ -429,14 +428,14 @@ public class FcpConnection implements Closeable {
        /**
         * Notifies all listeners that an “UnknownPeerNoteType” message was
         * received.
-        *
+        * 
         * @see FcpListener#receivedUnknownPeerNoteType(FcpConnection,
         *      UnknownPeerNoteType)
         * @param unknownPeerNoteType
         *            The “UnknownPeerNoteType” message
         */
        private void fireReceivedUnknownPeerNoteType(UnknownPeerNoteType unknownPeerNoteType) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedUnknownPeerNoteType(this, unknownPeerNoteType);
                }
        }
@@ -444,53 +443,53 @@ public class FcpConnection implements Closeable {
        /**
         * Notifies all listeners that an “UnknownNodeIdentifier” message was
         * received.
-        *
+        * 
         * @see FcpListener#receivedUnknownNodeIdentifier(FcpConnection,
         *      UnknownNodeIdentifier)
         * @param unknownNodeIdentifier
         *            The “UnknownNodeIdentifier” message
         */
        private void fireReceivedUnknownNodeIdentifier(UnknownNodeIdentifier unknownNodeIdentifier) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedUnknownNodeIdentifier(this, unknownNodeIdentifier);
                }
        }
 
        /**
         * Notifies all listeners that a “ConfigData” message was received.
-        *
+        * 
         * @see FcpListener#receivedConfigData(FcpConnection, ConfigData)
         * @param configData
         *            The “ConfigData” message
         */
        private void fireReceivedConfigData(ConfigData configData) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedConfigData(this, configData);
                }
        }
 
        /**
         * Notifies all listeners that a “GetFailed” message was received.
-        *
+        * 
         * @see FcpListener#receivedGetFailed(FcpConnection, GetFailed)
         * @param getFailed
         *            The “GetFailed” message
         */
        private void fireReceivedGetFailed(GetFailed getFailed) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedGetFailed(this, getFailed);
                }
        }
 
        /**
         * Notifies all listeners that a “PutFailed” message was received.
-        *
+        * 
         * @see FcpListener#receivedPutFailed(FcpConnection, PutFailed)
         * @param putFailed
         *            The “PutFailed” message
         */
        private void fireReceivedPutFailed(PutFailed putFailed) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedPutFailed(this, putFailed);
                }
        }
@@ -498,28 +497,28 @@ public class FcpConnection implements Closeable {
        /**
         * Notifies all listeners that an “IdentifierCollision” message was
         * received.
-        *
+        * 
         * @see FcpListener#receivedIdentifierCollision(FcpConnection,
         *      IdentifierCollision)
         * @param identifierCollision
         *            The “IdentifierCollision” message
         */
        private void fireReceivedIdentifierCollision(IdentifierCollision identifierCollision) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedIdentifierCollision(this, identifierCollision);
                }
        }
 
        /**
         * Notifies all listeners that an “PersistentPutDir” message was received.
-        *
+        * 
         * @see FcpListener#receivedPersistentPutDir(FcpConnection,
         *      PersistentPutDir)
         * @param persistentPutDir
         *            The “PersistentPutDir” message
         */
        private void fireReceivedPersistentPutDir(PersistentPutDir persistentPutDir) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedPersistentPutDir(this, persistentPutDir);
                }
        }
@@ -527,54 +526,54 @@ public class FcpConnection implements Closeable {
        /**
         * Notifies all listeners that a “PersistentRequestRemoved” message was
         * received.
-        *
+        * 
         * @see FcpListener#receivedPersistentRequestRemoved(FcpConnection,
         *      PersistentRequestRemoved)
         * @param persistentRequestRemoved
         *            The “PersistentRequestRemoved” message
         */
        private void fireReceivedPersistentRequestRemoved(PersistentRequestRemoved persistentRequestRemoved) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedPersistentRequestRemoved(this, persistentRequestRemoved);
                }
        }
 
        /**
         * Notifies all listeners that a “SubscribedUSKUpdate” message was received.
-        *
+        * 
         * @see FcpListener#receivedSubscribedUSKUpdate(FcpConnection,
         *      SubscribedUSKUpdate)
         * @param subscribedUSKUpdate
         *            The “SubscribedUSKUpdate” message
         */
        private void fireReceivedSubscribedUSKUpdate(SubscribedUSKUpdate subscribedUSKUpdate) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedSubscribedUSKUpdate(this, subscribedUSKUpdate);
                }
        }
 
        /**
         * Notifies all listeners that a “PluginInfo” message was received.
-        *
+        * 
         * @see FcpListener#receivedPluginInfo(FcpConnection, PluginInfo)
         * @param pluginInfo
         *            The “PluginInfo” message
         */
        private void fireReceivedPluginInfo(PluginInfo pluginInfo) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedPluginInfo(this, pluginInfo);
                }
        }
 
        /**
         * Notifies all listeners that an “FCPPluginReply” message was received.
-        *
+        * 
         * @see FcpListener#receivedFCPPluginReply(FcpConnection, FCPPluginReply)
         * @param fcpPluginReply
         *            The “FCPPluginReply” message
         */
        private void fireReceivedFCPPluginReply(FCPPluginReply fcpPluginReply) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedFCPPluginReply(this, fcpPluginReply);
                }
        }
@@ -582,78 +581,81 @@ public class FcpConnection implements Closeable {
        /**
         * Notifies all listeners that a “PersistentRequestModified” message was
         * received.
-        *
+        * 
         * @see FcpListener#receivedPersistentRequestModified(FcpConnection,
         *      PersistentRequestModified)
         * @param persistentRequestModified
         *            The “PersistentRequestModified” message
         */
        private void fireReceivedPersistentRequestModified(PersistentRequestModified persistentRequestModified) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedPersistentRequestModified(this, persistentRequestModified);
                }
        }
 
        /**
         * Notifies all listeners that a “PutSuccessful” message was received.
-        *
+        * 
         * @see FcpListener#receivedPutSuccessful(FcpConnection, PutSuccessful)
         * @param putSuccessful
         *            The “PutSuccessful” message
         */
        private void fireReceivedPutSuccessful(PutSuccessful putSuccessful) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedPutSuccessful(this, putSuccessful);
                }
        }
 
        /**
         * Notifies all listeners that a “PutFetchable” message was received.
-        *
+        * 
         * @see FcpListener#receivedPutFetchable(FcpConnection, PutFetchable)
         * @param putFetchable
         *            The “PutFetchable” message
         */
        private void fireReceivedPutFetchable(PutFetchable putFetchable) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedPutFetchable(this, putFetchable);
                }
        }
 
        /**
         * Notifies all listeners that a “ProtocolError” message was received.
-        *
+        * 
         * @see FcpListener#receivedProtocolError(FcpConnection, ProtocolError)
         * @param protocolError
         *            The “ProtocolError” message
         */
        private void fireReceivedProtocolError(ProtocolError protocolError) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedProtocolError(this, protocolError);
                }
        }
 
        /**
         * Notifies all registered listeners that a message has been received.
-        *
+        * 
         * @see FcpListener#receivedMessage(FcpConnection, FcpMessage)
         * @param fcpMessage
         *            The message that was received
         */
        private void fireMessageReceived(FcpMessage fcpMessage) {
-               for (FcpListener fcpListener: fcpListeners) {
+               for (FcpListener fcpListener : fcpListeners) {
                        fcpListener.receivedMessage(this, fcpMessage);
                }
        }
 
        /**
         * Notifies all listeners that the connection to the node was closed.
-        *
-        * @see FcpListener#connectionClosed(FcpConnection)
+        * 
+        * @param throwable
+        *            The exception that caused the disconnect, or <code>null</code>
+        *            if there was no exception
+        * @see FcpListener#connectionClosed(FcpConnection, Throwable)
         */
-       private void fireConnectionClosed() {
-               for (FcpListener fcpListener: fcpListeners) {
-                       fcpListener.connectionClosed(this);
+       private void fireConnectionClosed(Throwable throwable) {
+               for (FcpListener fcpListener : fcpListeners) {
+                       fcpListener.connectionClosed(this, throwable);
                }
        }
 
@@ -663,7 +665,7 @@ public class FcpConnection implements Closeable {
 
        /**
         * Connects to the node.
-        *
+        * 
         * @throws IOException
         *             if an I/O error occurs
         * @throws IllegalStateException
@@ -683,7 +685,7 @@ public class FcpConnection implements Closeable {
        /**
         * Disconnects from the node. If there is no connection to the node, this
         * method does nothing.
-        *
+        * 
         * @deprecated Use {@link #close()} instead
         */
        @Deprecated
@@ -696,19 +698,12 @@ public class FcpConnection implements Closeable {
         * does nothing.
         */
        public void close() {
-               if (connectionHandler == null) {
-                       return;
-               }
-               logger.info("disconnecting…");
-               FcpUtils.close(remoteSocket);
-               connectionHandler.stop();
-               connectionHandler = null;
-               fireConnectionClosed();
+               handleDisconnect(null);
        }
 
        /**
         * Sends the given FCP message.
-        *
+        * 
         * @param fcpMessage
         *            The FCP message to send
         * @throws IOException
@@ -726,7 +721,7 @@ public class FcpConnection implements Closeable {
        /**
         * Handles the given message, notifying listeners. This message should only
         * be called by {@link FcpConnectionHandler}.
-        *
+        * 
         * @param fcpMessage
         *            The received message
         */
@@ -823,13 +818,20 @@ public class FcpConnection implements Closeable {
 
        /**
         * Handles a disconnect from the node.
+        * 
+        * @param throwable
+        *            The exception that caused the disconnect, or <code>null</code>
+        *            if there was no exception
         */
-       synchronized void handleDisconnect() {
+       synchronized void handleDisconnect(Throwable throwable) {
                FcpUtils.close(remoteInputStream);
                FcpUtils.close(remoteOutputStream);
                FcpUtils.close(remoteSocket);
-               connectionHandler = null;
-               fireConnectionClosed();
+               if (connectionHandler != null) {
+                       connectionHandler.stop();
+                       connectionHandler = null;
+                       fireConnectionClosed(throwable);
+               }
        }
 
        //
@@ -839,7 +841,7 @@ public class FcpConnection implements Closeable {
        /**
         * Incremets the counter in {@link #incomingMessageStatistics} by <cod>1</code>
         * for the given message name.
-        *
+        * 
         * @param name
         *            The name of the message to count
         */
@@ -854,7 +856,7 @@ public class FcpConnection implements Closeable {
 
        /**
         * Returns a limited input stream from the node’s input stream.
-        *
+        * 
         * @param dataLength
         *            The length of the stream
         * @return The limited input stream
@@ -869,9 +871,8 @@ public class FcpConnection implements Closeable {
        /**
         * A wrapper around an {@link InputStream} that only supplies a limit number
         * of bytes from the underlying input stream.
-        *
-        * @author <a href="mailto:dr@ina-germany.de">David Roden</a>
-        * @version $Id$
+        * 
+        * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
         */
        private static class LimitedInputStream extends FilterInputStream {
 
@@ -881,7 +882,7 @@ public class FcpConnection implements Closeable {
                /**
                 * Creates a new LimitedInputStream that supplies at most
                 * <code>length</code> bytes from the given input stream.
-                *
+                * 
                 * @param inputStream
                 *            The input stream
                 * @param length
@@ -946,7 +947,7 @@ public class FcpConnection implements Closeable {
                /**
                 * {@inheritDoc} This method does nothing, as {@link #mark(int)} and
                 * {@link #reset()} are not supported.
-                *
+                * 
                 * @see java.io.FilterInputStream#mark(int)
                 */
                @Override
@@ -956,7 +957,7 @@ public class FcpConnection implements Closeable {
 
                /**
                 * {@inheritDoc}
-                *
+                * 
                 * @see java.io.FilterInputStream#markSupported()
                 * @return <code>false</code>
                 */
@@ -968,7 +969,7 @@ public class FcpConnection implements Closeable {
                /**
                 * {@inheritDoc} This method does nothing, as {@link #mark(int)} and
                 * {@link #reset()} are not supported.
-                *
+                * 
                 * @see java.io.FilterInputStream#reset()
                 */
                @Override
@@ -979,7 +980,7 @@ public class FcpConnection implements Closeable {
                /**
                 * Consumes the input stream, i.e. read all bytes until the limit is
                 * reached.
-                *
+                * 
                 * @throws IOException
                 *             if an I/O error occurs
                 */