Author: toad
Date: 2006-03-03 21:38:55 +0000 (Fri, 03 Mar 2006)
New Revision: 8150
Added:
trunk/freenet/src/freenet/support/io/NullBucket.java
Modified:
trunk/freenet/src/freenet/client/ArchiveManager.java
trunk/freenet/src/freenet/client/async/ClientGetter.java
trunk/freenet/src/freenet/node/Version.java
trunk/freenet/src/freenet/node/fcp/ClientGet.java
trunk/freenet/src/freenet/node/fcp/FCPClient.java
trunk/freenet/src/freenet/node/fcp/FCPConnectionOutputHandler.java
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucketFactory.java
trunk/freenet/src/freenet/support/io/PersistentTempBucketFactory.java
Log:
487:
ClientGet { Persistence=forever, ReturnType=disk|none|direct } all work now.
Modified: trunk/freenet/src/freenet/client/ArchiveManager.java
===================================================================
--- trunk/freenet/src/freenet/client/ArchiveManager.java 2006-03-03
20:50:13 UTC (rev 8149)
+++ trunk/freenet/src/freenet/client/ArchiveManager.java 2006-03-03
21:38:55 UTC (rev 8150)
@@ -359,7 +359,7 @@
byte[] cipherKey = new byte[32];
random.nextBytes(cipherKey);
- PaddedEphemerallyEncryptedBucket encryptedBucket = new
PaddedEphemerallyEncryptedBucket(fb, 1024, random);
+ PaddedEphemerallyEncryptedBucket encryptedBucket = new
PaddedEphemerallyEncryptedBucket(fb, 1024, random, true);
return new TempStoreElement(myFile, fb, encryptedBucket);
}
Modified: trunk/freenet/src/freenet/client/async/ClientGetter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientGetter.java 2006-03-03
20:50:13 UTC (rev 8149)
+++ trunk/freenet/src/freenet/client/async/ClientGetter.java 2006-03-03
21:38:55 UTC (rev 8150)
@@ -70,6 +70,7 @@
try {
Logger.minor(this, "Copying - returnBucket not
respected by client.async");
BucketTools.copy(from, to);
+ from.free();
} catch (IOException e) {
onFailure(new
FetchException(FetchException.BUCKET_ERROR), state /* not strictly to blame,
but we're not ako ClientGetState... */);
}
Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-03-03 20:50:13 UTC (rev
8149)
+++ trunk/freenet/src/freenet/node/Version.java 2006-03-03 21:38:55 UTC (rev
8150)
@@ -20,7 +20,7 @@
public static final String protocolVersion = "1.0";
/** The build number of the current revision */
- private static final int buildNumber = 486;
+ private static final int buildNumber = 487;
/** Oldest build of Fred we will talk to */
private static final int lastGoodBuild = 475;
Modified: trunk/freenet/src/freenet/node/fcp/ClientGet.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientGet.java 2006-03-03 20:50:13 UTC
(rev 8149)
+++ trunk/freenet/src/freenet/node/fcp/ClientGet.java 2006-03-03 21:38:55 UTC
(rev 8150)
@@ -21,9 +21,12 @@
import freenet.support.Bucket;
import freenet.support.BucketTools;
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;
+import freenet.support.io.NullBucket;
/**
* A simple client fetch. This can of course fetch arbitrarily large
@@ -98,15 +101,28 @@
fctx.maxOutputLength = message.maxSize;
fctx.maxTempLength = message.maxTempSize;
this.returnType = message.returnType;
+ Bucket ret = null;
if(returnType == ClientGetMessage.RETURN_TYPE_DISK) {
this.targetFile = message.diskFile;
this.tempFile = message.tempFile;
- returnBucket = new FileBucket(message.tempFile, false,
false, false, false);
+ ret = new FileBucket(message.tempFile, false, false,
false, false);
+ } else if(returnType == ClientGetMessage.RETURN_TYPE_NONE) {
+ targetFile = null;
+ tempFile = null;
+ ret = new NullBucket();
} else {
- returnBucket = null;
targetFile = null;
tempFile = null;
+ try {
+ ret =
handler.server.node.persistentTempBucketFactory.makeEncryptedBucket();
+ } catch (IOException e) {
+ onFailure(new
FetchException(FetchException.BUCKET_ERROR), null);
+ getter = null;
+ returnBucket = null;
+ return;
+ }
}
+ returnBucket = ret;
getter = new ClientGetter(this, client.node.fetchScheduler,
uri, fctx, priorityClass, client, returnBucket);
}
@@ -163,11 +179,20 @@
getFailedMessage = new
GetFailedMessage(fs.subset("GetFailed"), false);
}
}
+ Bucket ret = null;
if(returnType == ClientGetMessage.RETURN_TYPE_DISK) {
- returnBucket = new FileBucket(tempFile, false, false,
false, false);
- } else
- returnBucket = null;
-
+ ret = new FileBucket(tempFile, false, false, false,
false);
+ } else if(returnType == ClientGetMessage.RETURN_TYPE_NONE) {
+ ret = new NullBucket();
+ } 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);
+ } else {
+ throw new IllegalArgumentException();
+ }
+ returnBucket = ret;
+
getter = new ClientGetter(this, client.node.fetchScheduler,
uri, fctx, priorityClass, client, returnBucket);
start();
}
@@ -192,18 +217,19 @@
public void onSuccess(FetchResult result, ClientGetter state) {
Bucket data = result.asBucket();
+ if(returnBucket != data)
+ Logger.error(this, "returnBucket = "+returnBucket+" but
onSuccess() data = "+data);
boolean dontFree = false;
// FIXME I don't think this is a problem in this case...? (Disk
write while locked..)
+ AllDataMessage adm = null;
synchronized(this) {
if(returnType == ClientGetMessage.RETURN_TYPE_DIRECT) {
// Send all the data at once
// FIXME there should be other options
- trySendDataFoundOrGetFailed();
- AllDataMessage m = new AllDataMessage(data,
identifier);
+ adm = new AllDataMessage(data, identifier);
if(persistenceType == PERSIST_CONNECTION)
- m.setFreeOnSent();
+ adm.setFreeOnSent();
dontFree = true;
- trySendAllDataMessage(m);
} else if(returnType ==
ClientGetMessage.RETURN_TYPE_NONE) {
// Do nothing
} else if(returnType ==
ClientGetMessage.RETURN_TYPE_DISK) {
@@ -221,7 +247,6 @@
}
if(!tempFile.renameTo(targetFile)) {
postFetchProtocolErrorMessage =
new ProtocolErrorMessage(ProtocolErrorMessage.COULD_NOT_RENAME_FILE, false,
null, identifier);
- trySendDataFoundOrGetFailed();
// Don't delete temp file, user
might want it.
}
} catch (FileNotFoundException e) {
@@ -237,13 +262,14 @@
}
}
progressPending = null;
- FCPMessage msg = new DataFoundMessage(result,
identifier);
this.foundDataLength = data.size();
this.foundDataMimeType = result.getMimeType();
this.succeeded = true;
finished = true;
}
trySendDataFoundOrGetFailed();
+ if(adm != null)
+ trySendAllDataMessage(adm);
if(!dontFree)
data.free();
finish();
@@ -253,17 +279,18 @@
FCPMessage msg;
- if(postFetchProtocolErrorMessage != null) {
- msg = postFetchProtocolErrorMessage;
- } else if(succeeded) {
+ if(succeeded) {
msg = new DataFoundMessage(foundDataLength,
foundDataMimeType, identifier);
} else {
msg = getFailedMessage;
}
FCPConnectionHandler conn = client.getConnection();
- if(conn != null)
+ if(conn != null) {
conn.outputHandler.queue(msg);
+ if(postFetchProtocolErrorMessage != null)
+
conn.outputHandler.queue(postFetchProtocolErrorMessage);
+ }
}
private void trySendAllDataMessage(AllDataMessage msg) {
@@ -408,6 +435,12 @@
}
}
}
+ // Return bucket
+ if(returnType == ClientGetMessage.RETURN_TYPE_DIRECT) {
+ PaddedEphemerallyEncryptedBucket b =
(PaddedEphemerallyEncryptedBucket) returnBucket;
+ fs.put("ReturnBucket.DecryptKey",
HexUtil.bytesToHex(b.getKey()));
+ fs.put("ReturnBucket.Filename",
((FileBucket)b.getUnderlying()).getName());
+ }
return fs;
}
Modified: trunk/freenet/src/freenet/node/fcp/FCPClient.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/FCPClient.java 2006-03-03 20:50:13 UTC
(rev 8149)
+++ trunk/freenet/src/freenet/node/fcp/FCPClient.java 2006-03-03 21:38:55 UTC
(rev 8150)
@@ -126,8 +126,9 @@
req = (ClientRequest)
clientRequestsByIdentifier.get(identifier);
if(req == null)
throw new
MessageInvalidException(ProtocolErrorMessage.NO_SUCH_IDENTIFIER, null,
identifier);
- else if(!(runningPersistentRequests.remove(req) ||
completedUnackedRequests.remove(req)))
+ else if(!(runningPersistentRequests.remove(req) |
completedUnackedRequests.remove(req)))
throw new
MessageInvalidException(ProtocolErrorMessage.NO_SUCH_IDENTIFIER, null,
identifier);
+ clientRequestsByIdentifier.remove(identifier);
}
server.forceStorePersistentRequests();
}
Modified: trunk/freenet/src/freenet/node/fcp/FCPConnectionOutputHandler.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/FCPConnectionOutputHandler.java
2006-03-03 20:50:13 UTC (rev 8149)
+++ trunk/freenet/src/freenet/node/fcp/FCPConnectionOutputHandler.java
2006-03-03 21:38:55 UTC (rev 8150)
@@ -56,6 +56,7 @@
}
public void queue(FCPMessage msg) {
+ if(msg == null) throw new NullPointerException();
synchronized(outQueue) {
outQueue.add(msg);
outQueue.notifyAll();
Modified:
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java
2006-03-03 20:50:13 UTC (rev 8149)
+++ trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java
2006-03-03 21:38:55 UTC (rev 8150)
@@ -22,6 +22,8 @@
private final int minPaddedSize;
private final RandomSource origRandom;
private final Rijndael aes;
+ /** The decryption key. May be null. */
+ private final byte[] key;
private long dataLength;
private boolean readOnly;
private int lastOutputStream;
@@ -34,7 +36,7 @@
* @param origRandom Hard random number generator from which to obtain
a seed for padding.
* @throws UnsupportedCipherException
*/
- public PaddedEphemerallyEncryptedBucket(Bucket bucket, int minSize,
RandomSource origRandom) {
+ public PaddedEphemerallyEncryptedBucket(Bucket bucket, int minSize,
RandomSource origRandom, boolean forgetKey) {
this.origRandom = origRandom;
this.bucket = bucket;
if(bucket.size() != 0) throw new
IllegalArgumentException("Bucket must be empty");
@@ -46,8 +48,13 @@
byte[] key = new byte[32];
origRandom.nextBytes(key);
aes.initialize(key);
- // Might as well blank it
- for(int i=0;i<key.length;i++) key[i] = 0;
+ if(forgetKey) {
+ // Might as well blank it
+ for(int i=0;i<key.length;i++) key[i] = 0;
+ this.key = null;
+ } else {
+ this.key = key;
+ }
this.minPaddedSize = minSize;
readOnly = false;
lastOutputStream = 0;
@@ -64,8 +71,7 @@
}
origRandom.nextBytes(key);
aes.initialize(key);
- // Might as well blank it
- for(int i=0;i<key.length;i++) key[i] = 0;
+ this.key = key;
this.minPaddedSize = minSize;
readOnly = false;
lastOutputStream = 0;
@@ -260,4 +266,11 @@
bucket.free();
}
+ /**
+ * Get the decryption key. May have been blanked out.
+ */
+ public byte[] getKey() {
+ return key;
+ }
+
}
Modified:
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucketFactory.java
===================================================================
---
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucketFactory.java
2006-03-03 20:50:13 UTC (rev 8149)
+++
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucketFactory.java
2006-03-03 21:38:55 UTC (rev 8150)
@@ -22,7 +22,7 @@
}
public Bucket makeBucket(long size) throws IOException {
- return new
PaddedEphemerallyEncryptedBucket(baseFactory.makeBucket(size), minSize, random);
+ return new
PaddedEphemerallyEncryptedBucket(baseFactory.makeBucket(size), minSize, random,
true);
}
public void freeBucket(Bucket b) throws IOException {
Added: trunk/freenet/src/freenet/support/io/NullBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/io/NullBucket.java 2006-03-03
20:50:13 UTC (rev 8149)
+++ trunk/freenet/src/freenet/support/io/NullBucket.java 2006-03-03
21:38:55 UTC (rev 8150)
@@ -0,0 +1,64 @@
+package freenet.support.io;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import freenet.support.Bucket;
+
+public class NullBucket implements Bucket {
+
+ public final OutputStream nullOut = new NullOutputStream();
+ public final InputStream nullIn = new NullInputStream();
+
+ public final long length;
+
+ public NullBucket() {
+ this(0);
+ }
+
+ public NullBucket(long length) {
+ this.length = length;
+ }
+
+ /**
+ * Returns an OutputStream that is used to put data in this Bucket.
+ **/
+ public OutputStream getOutputStream() { return nullOut; }
+
+ /**
+ * Returns an InputStream that reads data from this Bucket. If there is
+ * no data in this bucket, null is returned.
+ **/
+ public InputStream getInputStream() { return nullIn; }
+
+ /**
+ * If resetWrite() is called on the object, the next getOutputStream
+ * should overwrite any other data in the bucket from the beginning,
+ * otherwise it should append it.
+ **/
+ public void resetWrite() {}
+
+ /**
+ * Returns the amount of data currently in this bucket.
+ **/
+ public long size() {
+ return length;
+ }
+
+ /** Returns the name of this NullBucket. */
+ public String getName() {
+ return "President George W. NullBucket";
+ }
+
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ public void setReadOnly() {
+ // Do nothing
+ }
+
+ public void free() {
+ // Do nothing
+ }
+}
+
Modified: trunk/freenet/src/freenet/support/io/PersistentTempBucketFactory.java
===================================================================
--- trunk/freenet/src/freenet/support/io/PersistentTempBucketFactory.java
2006-03-03 20:50:13 UTC (rev 8149)
+++ trunk/freenet/src/freenet/support/io/PersistentTempBucketFactory.java
2006-03-03 21:38:55 UTC (rev 8150)
@@ -85,8 +85,7 @@
public void completedInit() {
Iterator i = originalFiles.iterator();
while(i.hasNext()) {
- String s = (String) (i.next());
- File f = new File(s);
+ File f = (File) (i.next());
f.delete();
}
}
@@ -97,7 +96,7 @@
public Bucket makeEncryptedBucket() throws IOException {
Bucket b = makeBucket(-1);
- return new PaddedEphemerallyEncryptedBucket(b, 1024, rand);
+ return new PaddedEphemerallyEncryptedBucket(b, 1024, rand,
false);
}
public Bucket registerEncryptedBucket(String filename, byte[] key) {