wormarc:281dc0f92367
diff --git a/alien/src/wormarc/io/FCPCommandRunner.java b/alien/src/wormarc/io/FCPCommandRunner.java
--- a/alien/src/wormarc/io/FCPCommandRunner.java
+++ b/alien/src/wormarc/io/FCPCommandRunner.java
@@ -24,6 +24,7 @@
package wormarc.io;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
@@ -63,6 +64,9 @@ public class FCPCommandRunner {
private final static String REAL_TIME_FIELD = "RealTimeFlag";
private final static String REAL_TIME_VALUE = "true";
+ // If a request takes longer than this it is assumed to have timed out.
+ private final static int FOREVER_MS = 1000 * 60 * 60;
+
private static PrintStream sDebugOut = System.err;
protected static void debug(String msg) {
@@ -330,7 +334,6 @@ public class FCPCommandRunner {
}
}
-
static class GetTopKey extends Command {
private FreenetTopKey mTopKey;
protected GetTopKey(String name, String uri, FCPCommandRunner runner) {
@@ -388,6 +391,47 @@ public class FCPCommandRunner {
}
}
+ static class InvertPrivateKey extends Command {
+ private long mLength;
+ private InputStream mData;
+
+ public InvertPrivateKey(String name, String privateSSK, FCPCommandRunner runner) {
+ super(name, privateSSK + "inverting", runner);
+ byte[] raw = new byte[] {'d', 'u','m', 'm', 'y'};
+ mLength = raw.length;
+ mData = new ByteArrayInputStream(raw);
+ }
+
+ public long getLength() { return mLength; }
+
+ // Can return null.
+ public String getPublicSSK() {
+ // SSK@/kRM~jJVREwnN2qnA8R0Vt8HmpfRzBZ0j4rHC2cQ-0hw,2xcoQVdQLyqfTpF2DpkdUIbHFCeL4W~2X1phUYymnhM,AQACAAE/
+ final String KEY_START = "SSK@";
+ final String KEY_END = ",AQACAAE/";
+ final int pos = mUri.indexOf(KEY_END);
+ if (mUri == null || !mUri.startsWith(KEY_START) || mUri.indexOf(KEY_END) == -1) {
+ return null;
+ }
+ return mUri.substring(0, pos + KEY_END.length());
+ }
+
+ protected void handleData(long length, InputStream data) throws IOException {
+ handleDone("Not expecting AllData");
+ }
+
+ protected FcpMessage getStartMessage() {
+ ClientPut msg = new ClientPut(mUri, mFcpId);
+ msg.setDataLength(mLength);
+ msg.setPayloadInputStream(mData);
+ msg.setVerbosity(VERBOSITY);
+ msg.setDontCompress(DONT_COMPRESS);
+ msg.setPriority(PRIORITY);
+ msg.setGetCHKOnly(true); // Also works for SSKs.
+ return msg;
+ }
+ }
+
////////////////////////////////////////////////////////////
private List<Command> mPending = new ArrayList<Command>();
private FcpConnection mConnection;
@@ -448,18 +492,32 @@ public class FCPCommandRunner {
return cmd;
}
+ public synchronized InvertPrivateKey sendInvertPrivateKey(String privateSSKKey) throws IOException {
+ InvertPrivateKey cmd = new InvertPrivateKey("invert_private_ssk", privateSSKKey, this);
+ start(cmd);
+ return cmd;
+ }
+
public synchronized int getPendingCount() {
return mPending.size();
}
// DCI: make this call raiseOnFailure for each request?
- // DCI: timeout
- public synchronized void waitUntilAllFinished() throws InterruptedException {
+ public synchronized void waitUntilAllFinished(int timeoutMs) throws InterruptedException {
+ long maxTimeMs = System.currentTimeMillis() + timeoutMs;
while (mPending.size() > 0) {
+ if (System.currentTimeMillis() > maxTimeMs) {
+ // DCI:, LATER: Is this 100% correct. Should I be setting the interrupted flag too?
+ throw new InterruptedException("Timed out before all requests finished.");
+ }
wait(250);
}
}
+ public synchronized void waitUntilAllFinished() throws InterruptedException {
+ waitUntilAllFinished(FOREVER_MS);
+ }
+
protected synchronized void start(Command cmd) throws IOException {
if (mPending.contains(cmd)) {
throw new IllegalStateException("Command already started!");
diff --git a/alien/src/wormarc/io/FreenetIO.java b/alien/src/wormarc/io/FreenetIO.java
--- a/alien/src/wormarc/io/FreenetIO.java
+++ b/alien/src/wormarc/io/FreenetIO.java
@@ -137,6 +137,26 @@ public class FreenetIO implements Archiv
mPreviousTopKey = readTopKey(topKeyUri);
}
+ public String invertPrivateSSK(String privateSSKKey, int timeoutMs) throws IOException {
+ FCPCommandRunner runner = null;
+ try {
+ runner = new FCPCommandRunner(mHost, mPort,
+ mClientName +
+ IOUtil.randomHexString(12));
+
+ FCPCommandRunner.InvertPrivateKey invert = runner.sendInvertPrivateKey(privateSSKKey);
+ runner.waitUntilAllFinished(timeoutMs);
+ return invert.getPublicSSK();
+
+ } catch (InterruptedException ie) {
+ throw new IOException("Timed out waiting for FCP command.", ie);
+ } finally {
+ if (runner != null) {
+ runner.disconnect();
+ }
+ }
+ }
+
// DCI: BUG: redundant inserts are not supported yet. False assumption Block <-> CHK
// Updates the request URI on success.
public void write(HistoryLinkMap linkMap, List<Block> blocks, List<Archive.RootObject> rootObjects) throws IOException {