Author: toad
Date: 2008-02-29 15:51:23 +0000 (Fri, 29 Feb 2008)
New Revision: 18249

Modified:
   trunk/freenet/src/freenet/node/FailureTable.java
   trunk/freenet/src/freenet/node/NodeDispatcher.java
Log:
Offered-key sends: unlock only after the send has finished.

Modified: trunk/freenet/src/freenet/node/FailureTable.java
===================================================================
--- trunk/freenet/src/freenet/node/FailureTable.java    2008-02-29 15:30:33 UTC 
(rev 18248)
+++ trunk/freenet/src/freenet/node/FailureTable.java    2008-02-29 15:51:23 UTC 
(rev 18249)
@@ -6,6 +6,7 @@
 import java.lang.ref.WeakReference;
 import java.util.Vector;

+import freenet.io.comm.AsyncMessageCallback;
 import freenet.io.comm.ByteCounter;
 import freenet.io.comm.DMT;
 import freenet.io.comm.Message;
@@ -20,6 +21,7 @@
 import freenet.keys.SSKBlock;
 import freenet.support.LRUHashtable;
 import freenet.support.Logger;
+import freenet.support.io.NativeThread;

 // FIXME it is ESSENTIAL that we delete the ULPR data on requestors etc once 
we have found the key.
 // Otherwise it will be much too easy to trace a request if an attacker busts 
the node afterwards.
@@ -335,14 +337,15 @@

        /**
         * We offered a key, a node has responded to the offer. Note that this 
runs on the incoming
-        * packets thread so should allocate a new thread if it does anything 
heavy.
+        * packets thread so should allocate a new thread if it does anything 
heavy. Note also that
+        * it is responsible for unlocking the UID.
         * @param key The key to send.
         * @param isSSK Whether it is an SSK.
         * @param uid The UID.
         * @param source The node that asked for the key.
         * @throws NotConnectedException If the sender ceases to be connected.
         */
-       public void sendOfferedKey(Key key, boolean isSSK, boolean needPubKey, 
long uid, PeerNode source) throws NotConnectedException {
+       public void sendOfferedKey(Key key, final boolean isSSK, boolean 
needPubKey, final long uid, PeerNode source) throws NotConnectedException {
                if(isSSK) {
                        SSKBlock block = node.fetch((NodeSSK)key, false);
                        if(block == null) {
@@ -352,7 +355,31 @@
                        }
                        Message df = DMT.createFNPSSKDataFound(uid, 
block.getRawHeaders(), block.getRawData());
                        node.sentPayload(block.getRawData().length);
-                       source.sendAsync(df, null, 0, senderCounter);
+                       source.sendAsync(df, new AsyncMessageCallback() {
+                               boolean finished = false;
+                               public synchronized void acknowledged() {
+                                       if(finished) return;
+                                       finished = true;
+                                       node.unlockUID(uid, isSSK, false, 
false, true);
+                               }
+
+                               public void disconnected() {
+                                       if(finished) return;
+                                       finished = true;
+                                       node.unlockUID(uid, isSSK, false, 
false, true);
+                               }
+
+                               public void fatalError() {
+                                       if(finished) return;
+                                       finished = true;
+                                       node.unlockUID(uid, isSSK, false, 
false, true);
+                               }
+
+                               public void sent() {
+                                       // Ignore
+                               }
+                               
+                       }, 0, senderCounter);
                        if(needPubKey) {
                                Message pk = DMT.createFNPSSKPubKey(uid, 
block.getPubKey());
                                source.sendAsync(pk, null, 0, senderCounter);
@@ -368,9 +395,25 @@
                        source.sendAsync(df, null, 0, null);
                PartiallyReceivedBlock prb =
                        new PartiallyReceivedBlock(Node.PACKETS_IN_BLOCK, 
Node.PACKET_SIZE, block.getRawData());
-               BlockTransmitter bt =
+               final BlockTransmitter bt =
                        new BlockTransmitter(node.usm, source, uid, prb, 
node.outputThrottle, senderCounter);
-               bt.sendAsync(node.executor);
+               node.executor.execute(new PrioRunnable() {
+
+                               public int getPriority() {
+                                       return NativeThread.HIGH_PRIORITY;
+                               }
+
+                               public void run() {
+                                       try {
+                                               bt.send(node.executor);
+                                       } catch (Throwable t) {
+                                               Logger.error(this, "Sending 
offered key failed: "+t, t);
+                                       } finally {
+                                               node.unlockUID(uid, isSSK, 
false, false, true);
+                                       }
+                               }
+                       
+               }, "CHK offer sender");
                }
        }


Modified: trunk/freenet/src/freenet/node/NodeDispatcher.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeDispatcher.java  2008-02-29 15:30:33 UTC 
(rev 18248)
+++ trunk/freenet/src/freenet/node/NodeDispatcher.java  2008-02-29 15:51:23 UTC 
(rev 18249)
@@ -204,8 +204,9 @@
                // Do we want it? We can RejectOverload if we don't have the 
bandwidth...
                boolean isSSK = key instanceof NodeSSK;
                node.lockUID(uid, isSSK, false, true);
+               boolean needPubKey;
                try {
-               boolean needPubKey = m.getBoolean(DMT.NEED_PUB_KEY);
+               needPubKey = m.getBoolean(DMT.NEED_PUB_KEY);
                String reject = 
                        nodeStats.shouldRejectRequest(true, false, isSSK, 
false, true, source);
                if(reject != null) {
@@ -219,6 +220,14 @@
                        return true;
                }

+               } catch (Error e) {
+                       node.unlockUID(uid, isSSK, false, false, true);
+                       throw e;
+               } catch (RuntimeException e) {
+                       node.unlockUID(uid, isSSK, false, false, true);
+                       throw e;
+               } // Otherwise, sendOfferedKey is responsible for unlocking. 
+               
                // Accept it.

                try {
@@ -226,9 +235,6 @@
                } catch (NotConnectedException e) {
                        // Too bad.
                }
-               } finally {
-                       node.unlockUID(uid, isSSK, false, false, true);
-               }
                return true;
        }



Reply via email to