Author: toad
Date: 2006-01-13 18:09:01 +0000 (Fri, 13 Jan 2006)
New Revision: 7852

Modified:
   trunk/freenet/src/freenet/client/FileInserter.java
   trunk/freenet/src/freenet/client/InserterException.java
   trunk/freenet/src/freenet/keys/NodeSSK.java
   trunk/freenet/src/freenet/keys/SSKBlock.java
   trunk/freenet/src/freenet/node/LowLevelPutException.java
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/SSKInsertHandler.java
   trunk/freenet/src/freenet/node/SSKInsertSender.java
   trunk/freenet/src/freenet/node/Version.java
Log:
348: (mandatory) Working SSK collision detection.

Modified: trunk/freenet/src/freenet/client/FileInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/FileInserter.java  2006-01-13 17:17:44 UTC 
(rev 7851)
+++ trunk/freenet/src/freenet/client/FileInserter.java  2006-01-13 18:09:01 UTC 
(rev 7852)
@@ -263,6 +263,8 @@
                                                break;
                                        }
                                }
+                               if(le.code == LowLevelPutException.COLLISION)
+                                       break;
                        }
                }

@@ -284,6 +286,8 @@
                        throw new 
InserterException(InserterException.ROUTE_NOT_FOUND, uri);
                case LowLevelPutException.ROUTE_REALLY_NOT_FOUND:
                        throw new 
InserterException(InserterException.ROUTE_REALLY_NOT_FOUND, uri);
+               case LowLevelPutException.COLLISION:
+                       throw new 
InserterException(InserterException.COLLISION, uri);
                default:
                        Logger.error(this, "Unknown LowLevelPutException code: 
"+e.code+" on "+this);
                        throw new 
InserterException(InserterException.INTERNAL_ERROR, e, null);

Modified: trunk/freenet/src/freenet/client/InserterException.java
===================================================================
--- trunk/freenet/src/freenet/client/InserterException.java     2006-01-13 
17:17:44 UTC (rev 7851)
+++ trunk/freenet/src/freenet/client/InserterException.java     2006-01-13 
18:09:01 UTC (rev 7852)
@@ -72,6 +72,8 @@
        public static final int TOO_MANY_RETRIES_IN_BLOCKS = 7;
        /** Not able to leave the node at all */
        public static final int ROUTE_REALLY_NOT_FOUND = 8;
+       /** Collided with pre-existing content */
+       public static final int COLLISION = 9;

        public static String getMessage(int mode) {
                switch(mode) {
@@ -91,6 +93,8 @@
                        return "Could not propagate the insert to enough nodes 
(normal on small networks, try fetching it anyway)";
                case ROUTE_REALLY_NOT_FOUND:
                        return "Insert could not leave the node at all";
+               case COLLISION:
+                       return "Insert collided with different, pre-existing 
data at the same key";
                default:
                        return "Unknown error "+mode;
                }

Modified: trunk/freenet/src/freenet/keys/NodeSSK.java
===================================================================
--- trunk/freenet/src/freenet/keys/NodeSSK.java 2006-01-13 17:17:44 UTC (rev 
7851)
+++ trunk/freenet/src/freenet/keys/NodeSSK.java 2006-01-13 18:09:01 UTC (rev 
7852)
@@ -6,6 +6,7 @@
 import java.io.IOException;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;

 import freenet.crypt.DSAPublicKey;

@@ -103,4 +104,14 @@
                this.pubKey = pubKey2;
        }

+       public boolean equals(Object o) {
+               if(!(o instanceof NodeSSK)) return false;
+               NodeSSK key = (NodeSSK)o;
+               if(!Arrays.equals(key.encryptedHashedDocname, 
encryptedHashedDocname)) return false;
+               if(!Arrays.equals(key.pubKeyHash, pubKeyHash)) return false;
+               if(!Arrays.equals(key.routingKey, routingKey)) return false;
+               // cachedNormalizedDouble and pubKey could be negative/null.
+               return true;
+       }
+       
 }

Modified: trunk/freenet/src/freenet/keys/SSKBlock.java
===================================================================
--- trunk/freenet/src/freenet/keys/SSKBlock.java        2006-01-13 17:17:44 UTC 
(rev 7851)
+++ trunk/freenet/src/freenet/keys/SSKBlock.java        2006-01-13 18:09:01 UTC 
(rev 7852)
@@ -54,6 +54,20 @@

     static final short ENCRYPTED_HEADERS_LENGTH = 36;

+    public boolean equals(Object o) {
+       if(!(o instanceof SSKBlock)) return false;
+       SSKBlock block = (SSKBlock)o;
+
+       if(!block.pubKey.equals(pubKey)) return false;
+       if(!block.nodeKey.equals(nodeKey)) return false;
+       if(block.headersOffset != headersOffset) return false;
+       if(block.hashIdentifier != hashIdentifier) return false;
+       if(block.symCipherIdentifier != symCipherIdentifier) return false;
+       if(!Arrays.equals(block.headers, headers)) return false;
+       if(!Arrays.equals(block.data, data)) return false;
+       return true;
+    }
+    
        /**
         * Initialize, and verify data, headers against key. Provided
         * key must have a pubkey, or we throw.

Modified: trunk/freenet/src/freenet/node/LowLevelPutException.java
===================================================================
--- trunk/freenet/src/freenet/node/LowLevelPutException.java    2006-01-13 
17:17:44 UTC (rev 7851)
+++ trunk/freenet/src/freenet/node/LowLevelPutException.java    2006-01-13 
18:09:01 UTC (rev 7852)
@@ -11,6 +11,8 @@
        public static final int REJECTED_OVERLOAD = 3;
        /** Insert could not get off the node at all */
        public static final int ROUTE_REALLY_NOT_FOUND = 4;
+       /** Insert collided with pre-existing, different content. Can only 
happen with KSKs and SSKs. */
+       public static final int COLLISION = 5;

        /** Failure code */
        public final int code;
@@ -25,6 +27,8 @@
                        return "A node downstream either timed out or was 
overloaded (retry)";
                case ROUTE_REALLY_NOT_FOUND:
                        return "The insert could not get off the node at all";
+               case COLLISION:
+                       return "The insert collided with different data of the 
same key already on the network";
                default:
                        return "Unknown error code: "+reason;
                }

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2006-01-13 17:17:44 UTC (rev 
7851)
+++ trunk/freenet/src/freenet/node/Node.java    2006-01-13 18:09:01 UTC (rev 
7852)
@@ -830,6 +830,12 @@
                        insertThrottle.requestCompleted(len);
                }
         }
+
+        if(is.hasCollided()) {
+               // Store it locally so it can be fetched immediately, and 
overwrites any locally inserted.
+               store(is.getBlock());
+               throw new LowLevelPutException(LowLevelPutException.COLLISION);
+        }

         if(is.getStatus() == SSKInsertSender.SUCCESS) {
                Logger.normal(this, "Succeeded inserting "+block);
@@ -1054,6 +1060,24 @@
         transferringRequestSenders.put(key, sender);
     }

+    public synchronized SSKBlock fetch(NodeSSK key) {
+       try {
+               return sskDatastore.fetch(key, false);
+       } catch (IOException e) {
+               Logger.error(this, "Cannot fetch data: "+e, e);
+               return null;
+       }
+    }
+
+    public synchronized CHKBlock fetch(NodeCHK key) {
+       try {
+               return chkDatastore.fetch(key, false);
+       } catch (IOException e) {
+               Logger.error(this, "Cannot fetch data: "+e, e);
+               return null;
+       }
+    }
+    
     /**
      * Store a datum.
      */

Modified: trunk/freenet/src/freenet/node/SSKInsertHandler.java
===================================================================
--- trunk/freenet/src/freenet/node/SSKInsertHandler.java        2006-01-13 
17:17:44 UTC (rev 7851)
+++ trunk/freenet/src/freenet/node/SSKInsertHandler.java        2006-01-13 
18:09:01 UTC (rev 7852)
@@ -40,6 +40,7 @@
     private Thread runThread;
     private boolean sentSuccess;
     private boolean canCommit;
+    private boolean collided;

     SSKInsertHandler(Message req, long id, Node node, long startTime) {
         this.req = req;
@@ -128,8 +129,6 @@
                        }
                }

-               // Now we have the data, the headers and the pubkey. Commit it.
-               
                try {
                        key.setPubKey(pubKey);
                        block = new SSKBlock(data, headers, key, false);
@@ -143,8 +142,21 @@
                        }
                        return;
                }
-               Logger.minor(this, "Committed SSK "+key+" for "+uid);

+               SSKBlock storedBlock = node.fetch(key);
+               
+               if(storedBlock != null && !storedBlock.equals(block)) {
+                       Message msg = DMT.createFNPSSKDataFound(uid, 
storedBlock.getRawHeaders(), storedBlock.getRawData());
+                       try {
+                               source.send(msg);
+                       } catch (NotConnectedException e) {
+                               Logger.minor(this, "Lost connection to source 
on "+uid);
+                       }
+                       block = storedBlock;
+               }
+               
+               Logger.minor(this, "Got block for "+key+" for "+uid);
+               
         if(htl == 0) {
                Message msg = DMT.createFNPInsertReply(uid);
                sentSuccess = true;

Modified: trunk/freenet/src/freenet/node/SSKInsertSender.java
===================================================================
--- trunk/freenet/src/freenet/node/SSKInsertSender.java 2006-01-13 17:17:44 UTC 
(rev 7851)
+++ trunk/freenet/src/freenet/node/SSKInsertSender.java 2006-01-13 18:09:01 UTC 
(rev 7852)
@@ -11,6 +11,7 @@
 import freenet.io.comm.Message;
 import freenet.io.comm.MessageFilter;
 import freenet.io.comm.NotConnectedException;
+import freenet.keys.CHKBlock;
 import freenet.keys.NodeSSK;
 import freenet.keys.SSKBlock;
 import freenet.keys.SSKVerifyException;
@@ -51,6 +52,7 @@
     private boolean sentRequest;
     private boolean hasCollided;
     private boolean hasRecentlyCollided;
+    private SSKBlock block;

     /** Time at which we set status to a value other than NOT_FINISHED */
     private long setStatusTime = -1;
@@ -93,7 +95,7 @@
                } catch (NoSuchAlgorithmException e) {
                        throw new Error("SHA-256 not supported by system!: "+e);
                }
-       
+       this.block = block;
        startTime = System.currentTimeMillis();
         Thread t = new Thread(this, "SSKInsertSender for UID "+uid+" on 
"+node.portNumber+" at "+System.currentTimeMillis());
         t.setDaemon(true);
@@ -391,7 +393,7 @@
                                        }

                                        try {
-                                               SSKBlock newBlock = new 
SSKBlock(newData, newHeaders, myKey, false);
+                                               block = new SSKBlock(newData, 
newHeaders, myKey, false);
                                        } catch (SSKVerifyException e) {
                                                Logger.error(this, "Node sent 
us collision but got corrupt SSK!! from "+next+" on "+uid);
                                                // Try next node, no way to 
tell this one about its mistake as it's stopped listening. FIXME should it?
@@ -405,6 +407,7 @@
                                                hasCollided = true;
                                                notifyAll();
                                        }
+                                       break; // go to next node
                                }

                                if (msg.getSpec() != DMT.FNPInsertReply) {
@@ -510,4 +513,8 @@
                return data;
        }

+       public SSKBlock getBlock() {
+               return block;
+       }
+
 }

Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-01-13 17:17:44 UTC (rev 
7851)
+++ trunk/freenet/src/freenet/node/Version.java 2006-01-13 18:09:01 UTC (rev 
7852)
@@ -20,10 +20,10 @@
        public static final String protocolVersion = "1.0";

        /** The build number of the current revision */
-       public static final int buildNumber = 347;
+       public static final int buildNumber = 348;

        /** Oldest build of Fred we will talk to */
-       public static final int lastGoodBuild = 344;
+       public static final int lastGoodBuild = 348;

        /** The highest reported build of fred */
        public static int highestSeenBuild = buildNumber;


Reply via email to