Author: toad
Date: 2006-03-04 16:49:51 +0000 (Sat, 04 Mar 2006)
New Revision: 8156

Added:
   trunk/freenet/src/freenet/node/fcp/PersistenceParseException.java
Modified:
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/Version.java
   trunk/freenet/src/freenet/node/fcp/AllDataMessage.java
   trunk/freenet/src/freenet/node/fcp/ClientGet.java
   trunk/freenet/src/freenet/node/fcp/ClientPut.java
   trunk/freenet/src/freenet/node/fcp/ClientPutMessage.java
   trunk/freenet/src/freenet/node/fcp/ClientRequest.java
   trunk/freenet/src/freenet/node/fcp/DataCarryingMessage.java
   trunk/freenet/src/freenet/node/fcp/FCPConnectionInputHandler.java
   trunk/freenet/src/freenet/node/fcp/ProtocolErrorMessage.java
   trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java
   trunk/freenet/src/freenet/support/io/PersistentTempBucketFactory.java
Log:
490:
Fix persistent buckets.
Make ClientPut { Persistence=forever, UploadFrom=direct } work.

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2006-03-04 15:14:22 UTC (rev 
8155)
+++ trunk/freenet/src/freenet/node/Node.java    2006-03-04 16:49:51 UTC (rev 
8156)
@@ -836,7 +836,6 @@
         writeNodeFile();

         nodeConfig.finishedInitialization();
-        persistentTempBucketFactory.completedInit();

         // FIXME make all the below arbitrary constants configurable!

@@ -928,6 +927,8 @@
                if(testnetHandler != null)
                        testnetHandler.start();

+        persistentTempBucketFactory.completedInit();
+        
                Thread t = new Thread(ipDetector, "IP address re-detector");
                t.setDaemon(true);
                t.start();

Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-03-04 15:14:22 UTC (rev 
8155)
+++ trunk/freenet/src/freenet/node/Version.java 2006-03-04 16:49:51 UTC (rev 
8156)
@@ -20,7 +20,7 @@
        public static final String protocolVersion = "1.0";

        /** The build number of the current revision */
-       private static final int buildNumber = 489;
+       private static final int buildNumber = 490;

        /** Oldest build of Fred we will talk to */
        private static final int lastGoodBuild = 475;

Modified: trunk/freenet/src/freenet/node/fcp/AllDataMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/AllDataMessage.java      2006-03-04 
15:14:22 UTC (rev 8155)
+++ trunk/freenet/src/freenet/node/fcp/AllDataMessage.java      2006-03-04 
16:49:51 UTC (rev 8156)
@@ -39,4 +39,8 @@
                throw new 
MessageInvalidException(ProtocolErrorMessage.INVALID_MESSAGE, "AllData goes 
from server to client not the other way around", identifier);
        }

+       String getIdentifier() {
+               return identifier;
+       }
+
 }

Modified: trunk/freenet/src/freenet/node/fcp/ClientGet.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientGet.java   2006-03-04 15:14:22 UTC 
(rev 8155)
+++ trunk/freenet/src/freenet/node/fcp/ClientGet.java   2006-03-04 16:49:51 UTC 
(rev 8156)
@@ -130,9 +130,9 @@
         * Create a ClientGet from a request serialized to a SimpleFieldSet.
         * Can throw, and does minimal verification, as is dealing with data 
         * supposedly serialized out by the node.
-        * @throws MalformedURLException 
+        * @throws IOException 
         */
-       public ClientGet(SimpleFieldSet fs, FCPClient client2) throws 
MalformedURLException {
+       public ClientGet(SimpleFieldSet fs, FCPClient client2) throws 
IOException {
                uri = new FreenetURI(fs.get("URI"));
                identifier = fs.get("Identifier");
                verbosity = Integer.parseInt(fs.get("Verbosity"));
@@ -187,7 +187,7 @@
                } else if(returnType == ClientGetMessage.RETURN_TYPE_DIRECT) {
                        byte[] key = 
HexUtil.hexToBytes(fs.get("ReturnBucket.DecryptKey"));
                        String fnam = fs.get("ReturnBucket.Filename");
-                       ret = 
client.server.node.persistentTempBucketFactory.registerEncryptedBucket(fnam, 
key);
+                       ret = 
client.server.node.persistentTempBucketFactory.registerEncryptedBucket(fnam, 
key, succeeded ? foundDataLength : 0);
                } else {
                        throw new IllegalArgumentException();
                }

Modified: trunk/freenet/src/freenet/node/fcp/ClientPut.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPut.java   2006-03-04 15:14:22 UTC 
(rev 8155)
+++ trunk/freenet/src/freenet/node/fcp/ClientPut.java   2006-03-04 16:49:51 UTC 
(rev 8156)
@@ -24,7 +24,9 @@
 import freenet.keys.FreenetURI;
 import freenet.support.Bucket;
 import freenet.support.Fields;
+import freenet.support.HexUtil;
 import freenet.support.Logger;
+import freenet.support.PaddedEphemerallyEncryptedBucket;
 import freenet.support.SimpleFieldSet;
 import freenet.support.io.FileBucket;

@@ -100,9 +102,10 @@
         * Create from a persisted SimpleFieldSet.
         * Not very tolerant of errors, as the input was generated
         * by the node.
-        * @throws MalformedURLException 
+        * @throws PersistenceParseException 
+        * @throws IOException 
         */
-       public ClientPut(SimpleFieldSet fs, FCPClient client2) throws 
MalformedURLException {
+       public ClientPut(SimpleFieldSet fs, FCPClient client2) throws 
PersistenceParseException, IOException {
                uri = new FreenetURI(fs.get("URI"));
                identifier = fs.get("Identifier");
                verbosity = Integer.parseInt(fs.get("Verbosity"));
@@ -118,15 +121,28 @@
                boolean dontCompress = 
Fields.stringToBool(fs.get("DontCompress"), false);
                int maxRetries = Integer.parseInt(fs.get("MaxRetries"));
                clientToken = fs.get("ClientToken");
-               fromDisk = true;
-               origFilename = new File(fs.get("Filename"));
-               Bucket data = new FileBucket(origFilename, true, false, false, 
false);
+               fromDisk = Fields.stringToBool(fs.get("FromDisk"), false);
+               Bucket data;
+               if(fromDisk) {
+                       origFilename = new File(fs.get("Filename"));
+                       data = new FileBucket(origFilename, true, false, false, 
false);
+               } else {
+                       origFilename = null;
+                       byte[] key = 
HexUtil.hexToBytes(fs.get("TempBucket.DecryptKey"));
+                       String fnam = fs.get("TempBucket.Filename");
+                       long sz = Long.parseLong(fs.get("TempBucket.Size"));
+                       data = 
client.server.node.persistentTempBucketFactory.registerEncryptedBucket(fnam, 
key, sz);
+                       if(data.size() != sz)
+                               throw new PersistenceParseException("Size of 
bucket is wrong: "+data.size()+" should be "+sz);
+               }
                ctx = new InserterContext(client.defaultInsertContext, new 
SimpleEventProducer());
                ctx.dontCompress = dontCompress;
                ctx.eventProducer.addEventListener(this);
                ctx.maxInsertRetries = maxRetries;
                block = new InsertBlock(data, new ClientMetadata(mimeType), 
uri);
+               // FIXME uncomment after testing
                finished = Fields.stringToBool(fs.get("Finished"), false);
+               //finished = false;
                succeeded = Fields.stringToBool(fs.get("Succeeded"), false);
                String genURI = fs.get("GeneratedURI");
                if(genURI != null)
@@ -313,8 +329,16 @@
                // finished => persistence of completion state, pending messages
                //fs.put("Finished", Boolean.toString(finished));
                fs.put("ClientToken", clientToken);
-               if(!fromDisk) throw new 
UnsupportedOperationException("Persistent insert not from disk - NOT 
SUPPORTED");
-               fs.put("Filename", origFilename.getPath());
+               fs.put("FromDisk", Boolean.toString(fromDisk));
+               if(fromDisk) {
+                       fs.put("Filename", origFilename.getPath());
+               } else {
+                       // the bucket is a persistent encrypted temp bucket
+                       PaddedEphemerallyEncryptedBucket bucket = 
(PaddedEphemerallyEncryptedBucket) block.getData();
+                       fs.put("TempBucket.DecryptKey", 
HexUtil.bytesToHex(bucket.getKey()));
+                       fs.put("TempBucket.Filename", 
((FileBucket)(bucket.getUnderlying())).getName());
+                       fs.put("TempBucket.Size", Long.toString(bucket.size()));
+               }
                fs.put("DontCompress", Boolean.toString(ctx.dontCompress));
                fs.put("MaxRetries", Integer.toString(ctx.maxInsertRetries));
                fs.put("Finished", Boolean.toString(finished));

Modified: trunk/freenet/src/freenet/node/fcp/ClientPutMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutMessage.java    2006-03-04 
15:14:22 UTC (rev 8155)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutMessage.java    2006-03-04 
16:49:51 UTC (rev 8156)
@@ -1,13 +1,15 @@
 package freenet.node.fcp;

 import java.io.File;
+import java.io.IOException;
 import java.net.MalformedURLException;

 import freenet.keys.FreenetURI;
 import freenet.node.Node;
 import freenet.node.RequestStarter;
+import freenet.support.Bucket;
+import freenet.support.BucketFactory;
 import freenet.support.Fields;
-import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
 import freenet.support.io.FileBucket;

@@ -136,9 +138,6 @@
                } else {
                        throw new 
MessageInvalidException(ProtocolErrorMessage.ERROR_PARSING_NUMBER, "Error 
parsing Persistence field: "+persistenceString, identifier);
                }
-               if(persistenceType == ClientRequest.PERSIST_FOREVER && 
!fromDisk) {
-                       throw new 
MessageInvalidException(ProtocolErrorMessage.NOT_SUPPORTED, 
"Persistence=forever AND UploadFrom=direct unsupported!", identifier);
-               }
                clientToken = fs.get("ClientToken");
        }

@@ -167,4 +166,16 @@
                return dataLength;
        }

-}
+       String getIdentifier() {
+               return identifier;
+       }
+
+       Bucket createBucket(BucketFactory bf, long length, FCPServer server) 
throws IOException {
+               if(persistenceType == ClientRequest.PERSIST_FOREVER) {
+                       return 
server.node.persistentTempBucketFactory.makeEncryptedBucket();
+               } else {
+                       return super.createBucket(bf, length, server);
+               }
+       }
+       
+}
\ No newline at end of file

Modified: trunk/freenet/src/freenet/node/fcp/ClientRequest.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientRequest.java       2006-03-04 
15:14:22 UTC (rev 8155)
+++ trunk/freenet/src/freenet/node/fcp/ClientRequest.java       2006-03-04 
16:49:51 UTC (rev 8156)
@@ -67,17 +67,22 @@
                SimpleFieldSet fs = new SimpleFieldSet(br, true);
                String clientName = fs.get("ClientName");
                FCPClient client = server.registerClient(clientName, 
server.node, null);
-               String type = fs.get("Type");
-               if(type.equals("GET")) {
-                       ClientGet cg = new ClientGet(fs, client);
-                       client.register(cg);
-                       return cg;
-               } else if(type.equals("PUT")) {
-                       ClientPut cp = new ClientPut(fs, client);
-                       client.register(cp);
-                       return cp;
-               } else {
-                       Logger.error(ClientRequest.class, "Unrecognized type: 
"+type);
+               try {
+                       String type = fs.get("Type");
+                       if(type.equals("GET")) {
+                               ClientGet cg = new ClientGet(fs, client);
+                               client.register(cg);
+                               return cg;
+                       } else if(type.equals("PUT")) {
+                               ClientPut cp = new ClientPut(fs, client);
+                               client.register(cp);
+                               return cp;
+                       } else {
+                               Logger.error(ClientRequest.class, "Unrecognized 
type: "+type);
+                               return null;
+                       }
+               } catch (Throwable t) {
+                       Logger.error(ClientRequest.class, "Failed to parse: 
"+t, t);
                        return null;
                }
        }

Modified: trunk/freenet/src/freenet/node/fcp/DataCarryingMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/DataCarryingMessage.java 2006-03-04 
15:14:22 UTC (rev 8155)
+++ trunk/freenet/src/freenet/node/fcp/DataCarryingMessage.java 2006-03-04 
16:49:51 UTC (rev 8156)
@@ -7,6 +7,7 @@
 import freenet.support.Bucket;
 import freenet.support.BucketFactory;
 import freenet.support.BucketTools;
+import freenet.support.Logger;


 public abstract class DataCarryingMessage extends FCPMessage {
@@ -15,18 +16,30 @@

        abstract long dataLength();

+       Bucket createBucket(BucketFactory bf, long length, FCPServer server) 
throws IOException {
+               return bf.makeBucket(length);
+       }
+       
+       abstract String getIdentifier();
+
        protected boolean freeOnSent;

        void setFreeOnSent() {
                freeOnSent = true;
        }

-       public void readFrom(InputStream is, BucketFactory bf) throws 
IOException {
+       public void readFrom(InputStream is, BucketFactory bf, FCPServer 
server) throws IOException, MessageInvalidException {
                long len = dataLength();
                if(len < 0)
                        throw new IllegalArgumentException("Invalid length: 
"+len);
                if(len == 0) return;
-               Bucket bucket = bf.makeBucket(len);
+               Bucket bucket;
+               try {
+                       bucket = createBucket(bf, len, server);
+               } catch (IOException e) {
+                       Logger.error(this, "Bucket error: "+e, e);
+                       throw new 
MessageInvalidException(ProtocolErrorMessage.INTERNAL_ERROR, e.toString(), 
getIdentifier());
+               }
                BucketTools.copyFrom(bucket, is, len);
                this.bucket = bucket;
        }

Modified: trunk/freenet/src/freenet/node/fcp/FCPConnectionInputHandler.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/FCPConnectionInputHandler.java   
2006-03-04 15:14:22 UTC (rev 8155)
+++ trunk/freenet/src/freenet/node/fcp/FCPConnectionInputHandler.java   
2006-03-04 16:49:51 UTC (rev 8156)
@@ -66,7 +66,14 @@
                                continue;
                        }
                        if(msg instanceof DataCarryingMessage) {
-                               ((DataCarryingMessage)msg).readFrom(lis, 
handler.bf);
+                               // FIXME tidy up - coalesce with above and 
below try { } catch (MIE) {}'s?
+                               try {
+                                       
((DataCarryingMessage)msg).readFrom(lis, handler.bf, handler.server);
+                               } catch (MessageInvalidException e) {
+                                       FCPMessage err = new 
ProtocolErrorMessage(e.protocolCode, false, e.getMessage(), e.ident);
+                                       handler.outputHandler.queue(err);
+                                       continue;
+                               }
                        }
                        if((!firstMessage) && msg instanceof 
ClientHelloMessage) {
                                FCPMessage err = new 
ProtocolErrorMessage(ProtocolErrorMessage.NO_LATE_CLIENT_HELLOS, false, null, 
null);

Added: trunk/freenet/src/freenet/node/fcp/PersistenceParseException.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/PersistenceParseException.java   
2006-03-04 15:14:22 UTC (rev 8155)
+++ trunk/freenet/src/freenet/node/fcp/PersistenceParseException.java   
2006-03-04 16:49:51 UTC (rev 8156)
@@ -0,0 +1,12 @@
+package freenet.node.fcp;
+
+/**
+ * Thrown when a persistent request cannot be parsed.
+ */
+public class PersistenceParseException extends Exception {
+
+       public PersistenceParseException(String string) {
+               super(string);
+       }
+
+}

Modified: trunk/freenet/src/freenet/node/fcp/ProtocolErrorMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ProtocolErrorMessage.java        
2006-03-04 15:14:22 UTC (rev 8155)
+++ trunk/freenet/src/freenet/node/fcp/ProtocolErrorMessage.java        
2006-03-04 16:49:51 UTC (rev 8156)
@@ -35,6 +35,7 @@
        static final int COULD_NOT_RENAME_FILE = 14;
        static final int NO_SUCH_IDENTIFIER = 15;
        static final int NOT_SUPPORTED = 16;
+       static final int INTERNAL_ERROR = 17;

        final int code;
        final String extra;
@@ -75,6 +76,8 @@
                        return "No such identifier";
                case NOT_SUPPORTED:
                        return "Not supported";
+               case INTERNAL_ERROR:
+                       return "Internal error";
                default:
                        Logger.error(this, "Unknown error code: "+code, new 
Exception("debug"));
                return "(Unknown)";

Modified: 
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java     
2006-03-04 15:14:22 UTC (rev 8155)
+++ trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java     
2006-03-04 16:49:51 UTC (rev 8156)
@@ -60,16 +60,28 @@
                lastOutputStream = 0;
        }

-       public PaddedEphemerallyEncryptedBucket(Bucket bucket, int minSize, 
byte[] key, RandomSource origRandom) {
+       /**
+        * Load an existing PaddedEphemerallyEncryptedBucket, with a key.
+        * The bucket can and should already exist.
+        * @param bucket
+        * @param minSize
+        * @param knownSize The size of the data. This cannot be deduced from 
the bucket
+        * alone and must be specified. If the bucket is smaller than this, we 
throw.
+        * @param key
+        * @param origRandom
+        * @throws IOException 
+        */
+       public PaddedEphemerallyEncryptedBucket(Bucket bucket, int minSize, 
long knownSize, byte[] key, RandomSource origRandom) throws IOException {
+               if(bucket.size() < knownSize)
+                       throw new IOException("Bucket is too small on disk");
+               this.dataLength = knownSize;
                this.origRandom = origRandom;
                this.bucket = bucket;
-               if(bucket.size() != 0) throw new 
IllegalArgumentException("Bucket must be empty");
                try {
                        aes = new Rijndael(256, 256);
                } catch (UnsupportedCipherException e) {
                        throw new Error(e);
                }
-               origRandom.nextBytes(key);
                aes.initialize(key);
                this.key = key;
                this.minPaddedSize = minSize;

Modified: trunk/freenet/src/freenet/support/io/PersistentTempBucketFactory.java
===================================================================
--- trunk/freenet/src/freenet/support/io/PersistentTempBucketFactory.java       
2006-03-04 15:14:22 UTC (rev 8155)
+++ trunk/freenet/src/freenet/support/io/PersistentTempBucketFactory.java       
2006-03-04 16:49:51 UTC (rev 8156)
@@ -72,7 +72,7 @@
         * and to register this fact so that it is not deleted on startup 
completion.
         */
        public Bucket register(String filename) {
-               File f = new File(filename);
+               File f = new File(dir, filename);
                Bucket b = new FileBucket(f, false, false, false, true);
                originalFiles.remove(f);
                return b;
@@ -99,9 +99,9 @@
                return new PaddedEphemerallyEncryptedBucket(b, 1024, rand, 
false);
        }

-       public Bucket registerEncryptedBucket(String filename, byte[] key) {
+       public Bucket registerEncryptedBucket(String filename, byte[] key, long 
len) throws IOException {
                Bucket fileBucket = register(filename);
-               return new PaddedEphemerallyEncryptedBucket(fileBucket, 1024, 
key, rand);
+               return new PaddedEphemerallyEncryptedBucket(fileBucket, 1024, 
len, key, rand);
        }

        public void freeBucket(Bucket b) throws IOException {


Reply via email to