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 {