diff --git a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
index 275c200c2af420d186dfa08d64e0525da1180944..d19f929c275b22df983e31aef2655689e376140f 100644
--- a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
+++ b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
@@ -316,6 +316,40 @@ class EstablishmentManager {
         }
     }
 
+    /**
+     * Got a SessionDestroy on an established conn
+     */
+    void receiveSessionDestroy(RemoteHostId from, PeerState state) {
+        if (_log.shouldLog(Log.DEBUG))
+            _log.debug("Receive session destroy (EST) from: " + from);
+        _transport.dropPeer(state, false, "received destroy message");
+    }
+
+    /**
+     * Got a SessionDestroy during outbound establish
+     */
+    void receiveSessionDestroy(RemoteHostId from, OutboundEstablishState state) {
+        if (_log.shouldLog(Log.DEBUG))
+            _log.debug("Receive session destroy (OB) from: " + from);
+        _outboundStates.remove(from);
+        Hash peer = state.getRemoteIdentity().calculateHash();
+        _transport.dropPeer(peer, false, "received destroy message");
+    }
+
+    /**
+     * Got a SessionDestroy - maybe after an inbound establish
+     */
+    void receiveSessionDestroy(RemoteHostId from) {
+        if (_log.shouldLog(Log.DEBUG))
+            _log.debug("Receive session destroy (IB) from: " + from);
+        InboundEstablishState state = _inboundStates.remove(from);
+        if (state != null) {
+            Hash peer = state.getConfirmedIdentity().calculateHash();
+            if (peer != null)
+                _transport.dropPeer(peer, false, "received destroy message");
+        }
+    }
+
     /**
      * A data packet arrived on an outbound connection being established, which
      * means its complete (yay!).  This is a blocking call, more than I'd like...
diff --git a/router/java/src/net/i2p/router/transport/udp/PacketHandler.java b/router/java/src/net/i2p/router/transport/udp/PacketHandler.java
index 15dc164578eb016bf0dcf193a6ee8716a627f5a5..d130a4c8382c886b9c427bc0137f79d59f194fb1 100644
--- a/router/java/src/net/i2p/router/transport/udp/PacketHandler.java
+++ b/router/java/src/net/i2p/router/transport/udp/PacketHandler.java
@@ -186,6 +186,10 @@ class PacketHandler {
         }
     //}
 
+        /**
+         * Initial handling, called for every packet
+         * Find the state and call the correct receivePacket() variant
+         */
         private void handlePacket(UDPPacketReader reader, UDPPacket packet) {
             if (packet == null) return;
 
@@ -229,6 +233,10 @@ class PacketHandler {
             }
         }
 
+        /**
+         * Established conn
+         * Decrypt and validate the packet then call handlePacket()
+         */
         private void receivePacket(UDPPacketReader reader, UDPPacket packet, PeerState state) {
             _state = 17;
             boolean isValid = packet.validate(state.getCurrentMACKey());
@@ -280,6 +288,12 @@ class PacketHandler {
             _state = 26;
         }
 
+        /**
+         * New conn or failed validation
+         * Decrypt and validate the packet then call handlePacket()
+         *
+         * @param peerType OUTBOUND_FALLBACK, INBOUND_FALLBACK, or NEW_PEER
+         */
         private void receivePacket(UDPPacketReader reader, UDPPacket packet, short peerType) {
             _state = 27;
             boolean isValid = packet.validate(_transport.getIntroKey());
@@ -314,7 +328,11 @@ class PacketHandler {
         private void receivePacket(UDPPacketReader reader, UDPPacket packet, InboundEstablishState state) {
             receivePacket(reader, packet, state, true);
         }
+
         /**
+         * Inbound establishing conn
+         * Decrypt and validate the packet then call handlePacket()
+         *
          * @param allowFallback if it isn't valid for this establishment state, try as a non-establishment packet
          */
         private void receivePacket(UDPPacketReader reader, UDPPacket packet, InboundEstablishState state, boolean allowFallback) {
@@ -355,6 +373,10 @@ class PacketHandler {
             }
         }
 
+        /**
+         * Outbound establishing conn
+         * Decrypt and validate the packet then call handlePacket()
+         */
         private void receivePacket(UDPPacketReader reader, UDPPacket packet, OutboundEstablishState state) {
             _state = 35;
             if ( (state != null) && (_log.shouldLog(Log.DEBUG)) ) {
@@ -406,6 +428,10 @@ class PacketHandler {
 
         /**
          * Parse out the interesting bits and honor what it says
+         *
+         * @param state non-null if fully established
+         * @param outState non-null if outbound establishing in process
+         * @param inState unused always null
          */
         private void handlePacket(UDPPacketReader reader, UDPPacket packet, PeerState state, OutboundEstablishState outState, InboundEstablishState inState) {
             _state = 43;
@@ -527,7 +553,12 @@ class PacketHandler {
                     break;
                 case UDPPacket.PAYLOAD_TYPE_SESSION_DESTROY:
                     _state = 53;
-                    //_TODO
+                    if (outState != null)
+                        _establisher.receiveSessionDestroy(from, outState);
+                    else if (state != null)
+                        _establisher.receiveSessionDestroy(from, state);
+                    else
+                        _establisher.receiveSessionDestroy(from);
                     break;
                 default:
                     _state = 52;
diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
index 5570b83893f2bc4b5449553e1929ee697bc5f769..e046c0a99dfc3b2c947d6cb6ddf645490fa82603 100644
--- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
+++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
@@ -838,7 +838,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
         if (state != null)
             dropPeer(state, shouldShitlist, why);
     }
-    private void dropPeer(PeerState peer, boolean shouldShitlist, String why) {
+
+    void dropPeer(PeerState peer, boolean shouldShitlist, String why) {
         if (_log.shouldLog(Log.WARN)) {
             long now = _context.clock().now();
             StringBuilder buf = new StringBuilder(4096);