Work around Java's insane lack of finalization guarantees
[ldk-java] / src / main / java / org / ldk / batteries / NioPeerHandler.java
index bf111729115492ba7e3c94c26645290b000794d3..53a5353c2738f5ac4f0f0b1e9e471269b2e50196 100644 (file)
@@ -5,6 +5,7 @@ import org.ldk.structs.*;
 
 import java.io.IOException;
 import java.lang.reflect.Field;
+import java.lang.ref.Reference;
 import java.util.LinkedList;
 import java.net.SocketAddress;
 import java.net.StandardSocketOptions;
@@ -174,10 +175,11 @@ public class NioPeerHandler {
                                 if (chan == null) continue;
                                 try {
                                     Peer peer = setup_socket(chan);
+                                    peer.key = chan.register(this.selector, SelectionKey.OP_READ, peer);
                                     Result_NonePeerHandleErrorZ res = this.peer_manager.new_inbound_connection(peer.descriptor);
-                                    if (res instanceof Result_NonePeerHandleErrorZ.Result_NonePeerHandleErrorZ_OK) {
-                                        peer.key = chan.register(this.selector, SelectionKey.OP_READ, peer);
-                                    }
+                                    if (res instanceof Result_NonePeerHandleErrorZ.Result_NonePeerHandleErrorZ_Err) {
+                                                                               peer.descriptor.disconnect_socket();
+                                                                       }
                                 } catch (IOException ignored) { }
                             }
                             continue; // There is no attachment so the rest of the loop is useless
@@ -216,7 +218,7 @@ public class NioPeerHandler {
                                     buf.get(read_bytes, 0, read);
                                     long read_result_pointer = bindings.PeerManager_read_event(
                                             peer_manager_raw_pointer, peer.descriptor_raw_pointer, read_bytes);
-                                    if (bindings.LDKCResult_boolPeerHandleErrorZ_result_ok(read_result_pointer)) {
+                                    if (bindings.CResult_boolPeerHandleErrorZ_is_ok(read_result_pointer)) {
                                         if (bindings.LDKCResult_boolPeerHandleErrorZ_get_ok(read_result_pointer)) {
                                             key.interestOps(key.interestOps() & (~SelectionKey.OP_READ));
                                         }
@@ -273,14 +275,17 @@ public class NioPeerHandler {
             throw new IOException("Timed out");
         }
         Peer peer = setup_socket(chan);
+        do_selector_action(() -> peer.key = chan.register(this.selector, SelectionKey.OP_READ, peer));
         Result_CVec_u8ZPeerHandleErrorZ res = this.peer_manager.new_outbound_connection(their_node_id, peer.descriptor);
         if (res instanceof  Result_CVec_u8ZPeerHandleErrorZ.Result_CVec_u8ZPeerHandleErrorZ_OK) {
             byte[] initial_bytes = ((Result_CVec_u8ZPeerHandleErrorZ.Result_CVec_u8ZPeerHandleErrorZ_OK) res).res;
             if (chan.write(ByteBuffer.wrap(initial_bytes)) != initial_bytes.length) {
+                peer.descriptor.disconnect_socket();
+                this.peer_manager.socket_disconnected(peer.descriptor);
                 throw new IOException("We assume TCP socket buffer is at least a single packet in length");
             }
-            do_selector_action(() -> peer.key = chan.register(this.selector, SelectionKey.OP_READ, peer));
         } else {
+            peer.descriptor.disconnect_socket();
             throw new IOException("LDK rejected outbound connection. This likely shouldn't ever happen.");
         }
     }
@@ -335,6 +340,7 @@ public class NioPeerHandler {
                 }
             } catch (IOException ignored) {}
         }
+        Reference.reachabilityFence(this.peer_manager); // Almost certainly overkill, but no harm in it
     }
 
     /**