mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-04-14 22:26:44 +00:00
Rhizome Java API: get decrypted payload
This commit is contained in:
parent
d16be8f42d
commit
2aec8f31a4
@ -54,6 +54,10 @@ public class JSONTokeniser {
|
||||
|
||||
public static class UnexpectedException extends JSONInputException
|
||||
{
|
||||
public UnexpectedException(String got) {
|
||||
super("unexpected " + got);
|
||||
}
|
||||
|
||||
public UnexpectedException(String got, Class expecting) {
|
||||
super("unexpected " + got + ", expecting " + expecting.getName());
|
||||
}
|
||||
@ -78,6 +82,10 @@ public class JSONTokeniser {
|
||||
|
||||
public static class UnexpectedTokenException extends UnexpectedException
|
||||
{
|
||||
public UnexpectedTokenException(Object got) {
|
||||
super(jsonTokenDescription(got));
|
||||
}
|
||||
|
||||
public UnexpectedTokenException(Object got, Class expecting) {
|
||||
super(jsonTokenDescription(got), expecting);
|
||||
}
|
||||
@ -115,6 +123,11 @@ public class JSONTokeniser {
|
||||
return n;
|
||||
}
|
||||
|
||||
public static void unexpected(Object tok) throws UnexpectedTokenException
|
||||
{
|
||||
throw new UnexpectedTokenException(tok);
|
||||
}
|
||||
|
||||
public static void match(Object tok, Token exactly) throws SyntaxException
|
||||
{
|
||||
if (tok != exactly)
|
||||
|
@ -39,6 +39,8 @@ import org.servalproject.servaldna.rhizome.RhizomeCommon;
|
||||
import org.servalproject.servaldna.rhizome.RhizomeBundleList;
|
||||
import org.servalproject.servaldna.rhizome.RhizomeManifestBundle;
|
||||
import org.servalproject.servaldna.rhizome.RhizomePayloadRawBundle;
|
||||
import org.servalproject.servaldna.rhizome.RhizomePayloadBundle;
|
||||
import org.servalproject.servaldna.rhizome.RhizomeException;
|
||||
import org.servalproject.servaldna.meshms.MeshMSCommon;
|
||||
import org.servalproject.servaldna.meshms.MeshMSConversationList;
|
||||
import org.servalproject.servaldna.meshms.MeshMSMessageList;
|
||||
@ -63,23 +65,28 @@ public class ServalDClient implements ServalDHttpConnectionFactory
|
||||
this.restfulPassword = restfulPassword;
|
||||
}
|
||||
|
||||
public RhizomeBundleList rhizomeListBundles() throws ServalDInterfaceException, IOException
|
||||
public RhizomeBundleList rhizomeListBundles() throws ServalDInterfaceException, IOException, RhizomeException
|
||||
{
|
||||
RhizomeBundleList list = new RhizomeBundleList(this);
|
||||
list.connect();
|
||||
return list;
|
||||
}
|
||||
|
||||
public RhizomeManifestBundle rhizomeManifest(BundleId bid) throws ServalDInterfaceException, IOException
|
||||
public RhizomeManifestBundle rhizomeManifest(BundleId bid) throws ServalDInterfaceException, IOException, RhizomeException
|
||||
{
|
||||
return RhizomeCommon.rhizomeManifest(this, bid);
|
||||
}
|
||||
|
||||
public RhizomePayloadRawBundle rhizomePayloadRaw(BundleId bid) throws ServalDInterfaceException, IOException
|
||||
public RhizomePayloadRawBundle rhizomePayloadRaw(BundleId bid) throws ServalDInterfaceException, IOException, RhizomeException
|
||||
{
|
||||
return RhizomeCommon.rhizomePayloadRaw(this, bid);
|
||||
}
|
||||
|
||||
public RhizomePayloadBundle rhizomePayload(BundleId bid) throws ServalDInterfaceException, IOException, RhizomeException
|
||||
{
|
||||
return RhizomeCommon.rhizomePayload(this, bid);
|
||||
}
|
||||
|
||||
public MeshMSConversationList meshmsListConversations(SubscriberId sid) throws ServalDInterfaceException, IOException, MeshMSException
|
||||
{
|
||||
MeshMSConversationList list = new MeshMSConversationList(this, sid);
|
||||
|
@ -68,7 +68,7 @@ public class RhizomeBundleList {
|
||||
return this.json != null;
|
||||
}
|
||||
|
||||
public void connect() throws IOException, ServalDInterfaceException
|
||||
public void connect() throws IOException, ServalDInterfaceException, RhizomeException
|
||||
{
|
||||
try {
|
||||
rowCount = 0;
|
||||
|
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Serval Project Inc.
|
||||
*
|
||||
* This file is part of Serval Software (http://www.servalproject.org)
|
||||
*
|
||||
* Serval Software is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This source code is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this source code; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package org.servalproject.servaldna.rhizome;
|
||||
|
||||
import org.servalproject.servaldna.ServalDInterfaceException;
|
||||
|
||||
/* This enum is a direct isomorphism from the C "enum rhizome_bundle_status" defined in rhizome.h.
|
||||
*/
|
||||
public enum RhizomeBundleStatus {
|
||||
ERROR(-1), // internal error
|
||||
NEW(0), // bundle is newer than store
|
||||
SAME(1), // same version already in store
|
||||
DUPLICATE(2), // equivalent bundle already in store
|
||||
OLD(3), // newer version already in store
|
||||
INVALID(4), // manifest is invalid
|
||||
FAKE(5), // manifest signature not valid
|
||||
INCONSISTENT(6), // manifest filesize/filehash does not match supplied payload
|
||||
NO_ROOM(7) // doesn't fit; store may contain more important bundles
|
||||
;
|
||||
|
||||
final public int code;
|
||||
|
||||
private RhizomeBundleStatus(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public static RhizomeBundleStatus fromCode(int code) throws InvalidException
|
||||
{
|
||||
RhizomeBundleStatus status = null;
|
||||
switch (code) {
|
||||
case -1: status = ERROR; break;
|
||||
case 0: status = NEW; break;
|
||||
case 1: status = SAME; break;
|
||||
case 2: status = DUPLICATE; break;
|
||||
case 3: status = OLD; break;
|
||||
case 4: status = INVALID; break;
|
||||
case 5: status = FAKE; break;
|
||||
case 6: status = INCONSISTENT; break;
|
||||
case 7: status = NO_ROOM; break;
|
||||
default: throw new InvalidException(code);
|
||||
}
|
||||
assert status.code == code;
|
||||
return status;
|
||||
}
|
||||
|
||||
public static class InvalidException extends ServalDInterfaceException
|
||||
{
|
||||
public InvalidException(int code) {
|
||||
super("invalid Rhizome bundle status code = " + code);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -28,6 +28,7 @@ import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.net.HttpURLConnection;
|
||||
import org.servalproject.json.JSONTokeniser;
|
||||
import org.servalproject.json.JSONInputException;
|
||||
@ -43,13 +44,22 @@ import org.servalproject.servaldna.ServalDFailureException;
|
||||
public class RhizomeCommon
|
||||
{
|
||||
|
||||
protected static InputStream receiveResponse(HttpURLConnection conn, int expected_response_code) throws IOException, ServalDInterfaceException
|
||||
private static class Status {
|
||||
public int http_status_code;
|
||||
public String http_status_message;
|
||||
RhizomeBundleStatus bundle_status_code;
|
||||
String bundle_status_message;
|
||||
RhizomePayloadStatus payload_status_code;
|
||||
String payload_status_message;
|
||||
}
|
||||
|
||||
protected static InputStream receiveResponse(HttpURLConnection conn, int expected_response_code) throws IOException, ServalDInterfaceException, RhizomeException
|
||||
{
|
||||
int[] expected_response_codes = { expected_response_code };
|
||||
return receiveResponse(conn, expected_response_codes);
|
||||
}
|
||||
|
||||
protected static InputStream receiveResponse(HttpURLConnection conn, int[] expected_response_codes) throws IOException, ServalDInterfaceException
|
||||
protected static InputStream receiveResponse(HttpURLConnection conn, int[] expected_response_codes) throws IOException, ServalDInterfaceException, RhizomeException
|
||||
{
|
||||
for (int code: expected_response_codes) {
|
||||
if (conn.getResponseCode() == code)
|
||||
@ -60,18 +70,64 @@ public class RhizomeCommon
|
||||
if (conn.getResponseCode() == HttpURLConnection.HTTP_FORBIDDEN) {
|
||||
JSONTokeniser json = new JSONTokeniser(new InputStreamReader(conn.getErrorStream(), "US-ASCII"));
|
||||
Status status = decodeRestfulStatus(json);
|
||||
throw new ServalDInterfaceException("unexpected Rhizome failure, \"" + status.message + "\"");
|
||||
throwRestfulResponseExceptions(status, conn.getURL());
|
||||
throw new ServalDInterfaceException(
|
||||
"unexpected Rhizome failure, \"" + status.http_status_message + "\""
|
||||
+ (status.bundle_status_code == null ? "" : ", " + status.bundle_status_code)
|
||||
+ (status.bundle_status_message == null ? "" : " \"" + status.bundle_status_message + "\"")
|
||||
+ (status.payload_status_code == null ? "" : ", " + status.payload_status_code)
|
||||
+ (status.payload_status_message == null ? "" : ", " + status.payload_status_message + "\"")
|
||||
);
|
||||
}
|
||||
throw new ServalDInterfaceException("unexpected HTTP response code: " + conn.getResponseCode());
|
||||
}
|
||||
|
||||
protected static JSONTokeniser receiveRestfulResponse(HttpURLConnection conn, int expected_response_code) throws IOException, ServalDInterfaceException
|
||||
protected static void throwRestfulResponseExceptions(Status status, URL url) throws RhizomeException, ServalDFailureException
|
||||
{
|
||||
if (status.bundle_status_code != null) {
|
||||
switch (status.bundle_status_code) {
|
||||
case ERROR:
|
||||
throw new ServalDFailureException("received rhizome_bundle_status_code=ERROR(-1) from " + url);
|
||||
case NEW:
|
||||
case SAME:
|
||||
case DUPLICATE:
|
||||
case OLD:
|
||||
case NO_ROOM:
|
||||
break;
|
||||
case INVALID:
|
||||
throw new RhizomeInvalidManifestException(url);
|
||||
case FAKE:
|
||||
throw new RhizomeFakeManifestException(url);
|
||||
case INCONSISTENT:
|
||||
throw new RhizomeInconsistencyException(url);
|
||||
}
|
||||
}
|
||||
if (status.payload_status_code != null) {
|
||||
switch (status.payload_status_code) {
|
||||
case ERROR:
|
||||
throw new ServalDFailureException("received rhizome_payload_status_code=ERROR(-1) from " + url);
|
||||
case EMPTY:
|
||||
case NEW:
|
||||
case STORED:
|
||||
case TOO_BIG:
|
||||
case EVICTED:
|
||||
break;
|
||||
case WRONG_SIZE:
|
||||
case WRONG_HASH:
|
||||
throw new RhizomeInconsistencyException(url);
|
||||
case CRYPTO_FAIL:
|
||||
throw new RhizomeDecryptionException(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static JSONTokeniser receiveRestfulResponse(HttpURLConnection conn, int expected_response_code) throws IOException, ServalDInterfaceException, RhizomeException
|
||||
{
|
||||
int[] expected_response_codes = { expected_response_code };
|
||||
return receiveRestfulResponse(conn, expected_response_codes);
|
||||
}
|
||||
|
||||
protected static JSONTokeniser receiveRestfulResponse(HttpURLConnection conn, int[] expected_response_codes) throws IOException, ServalDInterfaceException
|
||||
protected static JSONTokeniser receiveRestfulResponse(HttpURLConnection conn, int[] expected_response_codes) throws IOException, ServalDInterfaceException, RhizomeException
|
||||
{
|
||||
InputStream in = receiveResponse(conn, expected_response_codes);
|
||||
if (!conn.getContentType().equals("application/json"))
|
||||
@ -79,10 +135,6 @@ public class RhizomeCommon
|
||||
return new JSONTokeniser(new InputStreamReader(in, "US-ASCII"));
|
||||
}
|
||||
|
||||
private static class Status {
|
||||
public String message;
|
||||
}
|
||||
|
||||
protected static Status decodeRestfulStatus(JSONTokeniser json) throws IOException, ServalDInterfaceException
|
||||
{
|
||||
try {
|
||||
@ -90,12 +142,28 @@ public class RhizomeCommon
|
||||
json.consume(JSONTokeniser.Token.START_OBJECT);
|
||||
json.consume("http_status_code");
|
||||
json.consume(JSONTokeniser.Token.COLON);
|
||||
json.consume(Integer.class);
|
||||
status.http_status_code = json.consume(Integer.class);
|
||||
json.consume(JSONTokeniser.Token.COMMA);
|
||||
status.message = json.consume("http_status_message");
|
||||
json.consume("http_status_message");
|
||||
json.consume(JSONTokeniser.Token.COLON);
|
||||
String message = json.consume(String.class);
|
||||
json.consume(JSONTokeniser.Token.END_OBJECT);
|
||||
status.http_status_message = json.consume(String.class);
|
||||
Object tok = json.nextToken();
|
||||
while (tok == JSONTokeniser.Token.COMMA) {
|
||||
String label = json.consume(String.class);
|
||||
json.consume(JSONTokeniser.Token.COLON);
|
||||
if (label.equals("rhizome_bundle_status_code"))
|
||||
status.bundle_status_code = RhizomeBundleStatus.fromCode(json.consume(Integer.class));
|
||||
else if (label.equals("rhizome_bundle_status_message"))
|
||||
status.bundle_status_message = json.consume(String.class);
|
||||
else if (label.equals("rhizome_payload_status_code"))
|
||||
status.payload_status_code = RhizomePayloadStatus.fromCode(json.consume(Integer.class));
|
||||
else if (label.equals("rhizome_payload_status_message"))
|
||||
status.payload_status_message = json.consume(String.class);
|
||||
else
|
||||
json.unexpected(label);
|
||||
tok = json.nextToken();
|
||||
}
|
||||
json.match(tok, JSONTokeniser.Token.END_OBJECT);
|
||||
json.consume(JSONTokeniser.Token.EOF);
|
||||
return status;
|
||||
}
|
||||
@ -104,7 +172,7 @@ public class RhizomeCommon
|
||||
}
|
||||
}
|
||||
|
||||
public static RhizomeManifestBundle rhizomeManifest(ServalDHttpConnectionFactory connector, BundleId bid) throws IOException, ServalDInterfaceException
|
||||
public static RhizomeManifestBundle rhizomeManifest(ServalDHttpConnectionFactory connector, BundleId bid) throws IOException, ServalDInterfaceException, RhizomeException
|
||||
{
|
||||
HttpURLConnection conn = connector.newServalDHttpConnection("/restful/rhizome/" + bid.toHex() + ".rhm");
|
||||
conn.connect();
|
||||
@ -128,7 +196,7 @@ public class RhizomeCommon
|
||||
return new RhizomeManifestBundle(manifest, insertTime, author, secret);
|
||||
}
|
||||
|
||||
public static RhizomePayloadRawBundle rhizomePayloadRaw(ServalDHttpConnectionFactory connector, BundleId bid) throws IOException, ServalDInterfaceException
|
||||
public static RhizomePayloadRawBundle rhizomePayloadRaw(ServalDHttpConnectionFactory connector, BundleId bid) throws IOException, ServalDInterfaceException, RhizomeException
|
||||
{
|
||||
HttpURLConnection conn = connector.newServalDHttpConnection("/restful/rhizome/" + bid.toHex() + "/raw.bin");
|
||||
conn.connect();
|
||||
@ -143,6 +211,21 @@ public class RhizomeCommon
|
||||
return new RhizomePayloadRawBundle(manifest, in, insertTime, author, secret);
|
||||
}
|
||||
|
||||
public static RhizomePayloadBundle rhizomePayload(ServalDHttpConnectionFactory connector, BundleId bid) throws IOException, ServalDInterfaceException, RhizomeException
|
||||
{
|
||||
HttpURLConnection conn = connector.newServalDHttpConnection("/restful/rhizome/" + bid.toHex() + "/decrypted.bin");
|
||||
conn.connect();
|
||||
InputStream in = RhizomeCommon.receiveResponse(conn, HttpURLConnection.HTTP_OK);
|
||||
if (!conn.getContentType().equals("application/octet-stream"))
|
||||
throw new ServalDInterfaceException("unexpected HTTP Content-Type: " + conn.getContentType());
|
||||
dumpHeaders(conn, System.err);
|
||||
RhizomeManifest manifest = manifestFromHeaders(conn);
|
||||
long insertTime = headerUnsignedLong(conn, "Serval-Rhizome-Bundle-Inserttime");
|
||||
SubscriberId author = header(conn, "Serval-Rhizome-Bundle-Author", SubscriberId.class);
|
||||
BundleSecret secret = header(conn, "Serval-Rhizome-Bundle-Secret", BundleSecret.class);
|
||||
return new RhizomePayloadBundle(manifest, in, insertTime, author, secret);
|
||||
}
|
||||
|
||||
private static void dumpHeaders(HttpURLConnection conn, PrintStream out)
|
||||
{
|
||||
for (Map.Entry<String,List<String>> e: conn.getHeaderFields().entrySet())
|
||||
|
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Serval Project Inc.
|
||||
*
|
||||
* This file is part of Serval Software (http://www.servalproject.org)
|
||||
*
|
||||
* Serval Software is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This source code is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this source code; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package org.servalproject.servaldna.rhizome;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Thrown when a Rhizome API method is asked to decrypt a payload without possessing the necessary
|
||||
* recipient identity (ie, is locked or not in the keyring).
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
public class RhizomeDecryptionException extends RhizomeException
|
||||
{
|
||||
public RhizomeDecryptionException(URL url) {
|
||||
super("cannot decrypt payload", url);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Serval Project Inc.
|
||||
*
|
||||
* This file is part of Serval Software (http://www.servalproject.org)
|
||||
*
|
||||
* Serval Software is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This source code is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this source code; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package org.servalproject.servaldna.rhizome;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Thrown when a Rhizome API encounters an exceptional condition. This exception is subclassed for
|
||||
* specific causes.
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
public abstract class RhizomeException extends Exception
|
||||
{
|
||||
public final URL url;
|
||||
|
||||
public RhizomeException(String message, URL url) {
|
||||
super(message + "; " + url);
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Serval Project Inc.
|
||||
*
|
||||
* This file is part of Serval Software (http://www.servalproject.org)
|
||||
*
|
||||
* Serval Software is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This source code is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this source code; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package org.servalproject.servaldna.rhizome;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Thrown when a Rhizome API method is passed a manifest with an invalid or missing signature.
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
public class RhizomeFakeManifestException extends RhizomeException
|
||||
{
|
||||
public RhizomeFakeManifestException(URL url) {
|
||||
super("unsigned manifest", url);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Serval Project Inc.
|
||||
*
|
||||
* This file is part of Serval Software (http://www.servalproject.org)
|
||||
*
|
||||
* Serval Software is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This source code is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this source code; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package org.servalproject.servaldna.rhizome;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Thrown when a Rhizome API method is passed a manifest which is inconsistent with a supplied
|
||||
* payload. I.e., filesize or filehash does not match.
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
public class RhizomeInconsistencyException extends RhizomeException
|
||||
{
|
||||
public RhizomeInconsistencyException(URL url) {
|
||||
super("manifest inconsistent with payload", url);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Serval Project Inc.
|
||||
*
|
||||
* This file is part of Serval Software (http://www.servalproject.org)
|
||||
*
|
||||
* Serval Software is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This source code is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this source code; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package org.servalproject.servaldna.rhizome;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Thrown when a Rhizome API method is passed an invalid manifest. This is not an error within the
|
||||
* Serval DNA interface, so it is not a subclass of ServalDInterfaceException. The programmer must
|
||||
* explicitly deal with it instead of just absorbing it as an interface malfunction.
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
public class RhizomeInvalidManifestException extends RhizomeException
|
||||
{
|
||||
public RhizomeInvalidManifestException(URL url) {
|
||||
super("invalid manifest", url);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Serval Project Inc.
|
||||
*
|
||||
* This file is part of Serval Software (http://www.servalproject.org)
|
||||
*
|
||||
* Serval Software is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This source code is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this source code; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package org.servalproject.servaldna.rhizome;
|
||||
|
||||
import java.io.InputStream;
|
||||
import org.servalproject.servaldna.SubscriberId;
|
||||
import org.servalproject.servaldna.BundleSecret;
|
||||
import org.servalproject.servaldna.ServalDInterfaceException;
|
||||
|
||||
public class RhizomePayloadBundle {
|
||||
|
||||
public final RhizomeManifest manifest;
|
||||
public final InputStream payloadInputStream;
|
||||
public final long insertTime;
|
||||
public final SubscriberId author;
|
||||
public final BundleSecret secret;
|
||||
|
||||
protected RhizomePayloadBundle(RhizomeManifest manifest,
|
||||
InputStream payloadInputStream,
|
||||
long insertTime,
|
||||
SubscriberId author,
|
||||
BundleSecret secret)
|
||||
|
||||
{
|
||||
this.payloadInputStream = payloadInputStream;
|
||||
this.manifest = manifest;
|
||||
this.insertTime = insertTime;
|
||||
this.author = author;
|
||||
this.secret = secret;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Serval Project Inc.
|
||||
*
|
||||
* This file is part of Serval Software (http://www.servalproject.org)
|
||||
*
|
||||
* Serval Software is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This source code is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this source code; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package org.servalproject.servaldna.rhizome;
|
||||
|
||||
import org.servalproject.servaldna.ServalDInterfaceException;
|
||||
|
||||
/* This enum is a direct isomorphism from the C "enum rhizome_payload_status" defined in rhizome.h.
|
||||
*/
|
||||
public enum RhizomePayloadStatus {
|
||||
ERROR(-1), // unexpected error (underlying failure)
|
||||
EMPTY(0), // payload is empty (zero length)
|
||||
NEW(1), // payload is not yet in store (added)
|
||||
STORED(2), // payload is already in store
|
||||
WRONG_SIZE(3), // payload's size does not match manifest
|
||||
WRONG_HASH(4), // payload's hash does not match manifest
|
||||
CRYPTO_FAIL(5), // cannot encrypt/decrypt (payload key unknown)
|
||||
TOO_BIG(6), // payload will never fit in our store
|
||||
EVICTED(7) // other payloads in our store are more important
|
||||
;
|
||||
|
||||
final public int code;
|
||||
|
||||
private RhizomePayloadStatus(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public static RhizomePayloadStatus fromCode(int code) throws InvalidException
|
||||
{
|
||||
RhizomePayloadStatus status = null;
|
||||
switch (code) {
|
||||
case -1: status = ERROR; break;
|
||||
case 0: status = EMPTY; break;
|
||||
case 1: status = NEW; break;
|
||||
case 2: status = STORED; break;
|
||||
case 3: status = WRONG_SIZE; break;
|
||||
case 4: status = WRONG_HASH; break;
|
||||
case 5: status = CRYPTO_FAIL; break;
|
||||
case 6: status = TOO_BIG; break;
|
||||
case 7: status = EVICTED; break;
|
||||
default: throw new InvalidException(code);
|
||||
}
|
||||
assert status.code == code;
|
||||
return status;
|
||||
}
|
||||
|
||||
public static class InvalidException extends ServalDInterfaceException
|
||||
{
|
||||
public InvalidException(int code) {
|
||||
super("invalid Rhizome payload status code = " + code);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -33,6 +33,8 @@ import org.servalproject.servaldna.rhizome.RhizomeListBundle;
|
||||
import org.servalproject.servaldna.rhizome.RhizomeBundleList;
|
||||
import org.servalproject.servaldna.rhizome.RhizomeManifestBundle;
|
||||
import org.servalproject.servaldna.rhizome.RhizomePayloadRawBundle;
|
||||
import org.servalproject.servaldna.rhizome.RhizomePayloadBundle;
|
||||
import org.servalproject.servaldna.rhizome.RhizomeException;
|
||||
|
||||
public class Rhizome {
|
||||
|
||||
@ -68,6 +70,9 @@ public class Rhizome {
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (RhizomeException e) {
|
||||
System.out.println(e.toString());
|
||||
}
|
||||
finally {
|
||||
if (list != null)
|
||||
list.close();
|
||||
@ -77,17 +82,22 @@ public class Rhizome {
|
||||
|
||||
static void rhizome_manifest(BundleId bid, String dstpath) throws ServalDInterfaceException, IOException, InterruptedException
|
||||
{
|
||||
ServalDClient client = new ServerControl().getRestfulClient();
|
||||
RhizomeManifestBundle bundle = client.rhizomeManifest(bid);
|
||||
System.out.println(
|
||||
"_insertTime=" + bundle.insertTime + "\n" +
|
||||
"_author=" + bundle.author + "\n" +
|
||||
"_secret=" + bundle.secret + "\n" +
|
||||
manifestFields(bundle.manifest, "\n") + "\n"
|
||||
);
|
||||
FileOutputStream out = new FileOutputStream(dstpath);
|
||||
out.write(bundle.manifestText());
|
||||
out.close();
|
||||
try {
|
||||
ServalDClient client = new ServerControl().getRestfulClient();
|
||||
RhizomeManifestBundle bundle = client.rhizomeManifest(bid);
|
||||
System.out.println(
|
||||
"_insertTime=" + bundle.insertTime + "\n" +
|
||||
"_author=" + bundle.author + "\n" +
|
||||
"_secret=" + bundle.secret + "\n" +
|
||||
manifestFields(bundle.manifest, "\n") + "\n"
|
||||
);
|
||||
FileOutputStream out = new FileOutputStream(dstpath);
|
||||
out.write(bundle.manifestText());
|
||||
out.close();
|
||||
}
|
||||
catch (RhizomeException e) {
|
||||
System.out.println(e.toString());
|
||||
}
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
@ -112,6 +122,40 @@ public class Rhizome {
|
||||
manifestFields(bundle.manifest, "\n") + "\n"
|
||||
);
|
||||
}
|
||||
catch (RhizomeException e) {
|
||||
System.out.println(e.toString());
|
||||
}
|
||||
finally {
|
||||
if (out != null)
|
||||
out.close();
|
||||
}
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
static void rhizome_payload_decrypted(BundleId bid, String dstpath) throws ServalDInterfaceException, IOException, InterruptedException
|
||||
{
|
||||
ServalDClient client = new ServerControl().getRestfulClient();
|
||||
FileOutputStream out = new FileOutputStream(dstpath);
|
||||
try {
|
||||
RhizomePayloadBundle bundle = client.rhizomePayload(bid);
|
||||
InputStream in = bundle.payloadInputStream;
|
||||
byte[] buf = new byte[4096];
|
||||
int n;
|
||||
while ((n = in.read(buf)) > 0)
|
||||
out.write(buf, 0, n);
|
||||
in.close();
|
||||
out.close();
|
||||
out = null;
|
||||
System.out.println(
|
||||
"_insertTime=" + bundle.insertTime + "\n" +
|
||||
"_author=" + bundle.author + "\n" +
|
||||
"_secret=" + bundle.secret + "\n" +
|
||||
manifestFields(bundle.manifest, "\n") + "\n"
|
||||
);
|
||||
}
|
||||
catch (RhizomeException e) {
|
||||
System.out.println(e.toString());
|
||||
}
|
||||
finally {
|
||||
if (out != null)
|
||||
out.close();
|
||||
@ -131,6 +175,8 @@ public class Rhizome {
|
||||
rhizome_manifest(new BundleId(args[1]), args[2]);
|
||||
else if (methodName.equals("rhizome-payload-raw"))
|
||||
rhizome_payload_raw(new BundleId(args[1]), args[2]);
|
||||
else if (methodName.equals("rhizome-payload-decrypted"))
|
||||
rhizome_payload_decrypted(new BundleId(args[1]), args[2]);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
|
@ -727,7 +727,7 @@ static int restful_rhizome_bid_raw_bin(httpd_request *r, const char *remainder)
|
||||
}
|
||||
int ret = rhizome_response_content_init_filehash(r, &r->manifest->filehash);
|
||||
if (ret)
|
||||
return ret;
|
||||
return http_request_rhizome_response(r, ret, NULL, NULL);
|
||||
http_request_response_generated(&r->http, 200, CONTENT_TYPE_BLOB, rhizome_payload_content);
|
||||
return 1;
|
||||
}
|
||||
@ -745,7 +745,7 @@ static int restful_rhizome_bid_decrypted_bin(httpd_request *r, const char *remai
|
||||
}
|
||||
int ret = rhizome_response_content_init_payload(r, r->manifest);
|
||||
if (ret)
|
||||
return ret;
|
||||
return http_request_rhizome_response(r, ret, NULL, NULL);
|
||||
// TODO use Content Type from manifest (once it is implemented)
|
||||
http_request_response_generated(&r->http, 200, CONTENT_TYPE_BLOB, rhizome_payload_content);
|
||||
return 1;
|
||||
|
@ -180,8 +180,44 @@ test_RhizomePayloadRaw() {
|
||||
executeJavaOk org.servalproject.test.Rhizome rhizome-payload-raw "${BID[$n]}" raw.bin$n
|
||||
tfw_cat --stdout --stderr
|
||||
assert_metadata $n
|
||||
done
|
||||
for n in 0 1 2 3; do
|
||||
assert cmp raw$n raw.bin$n
|
||||
done
|
||||
}
|
||||
|
||||
doc_RhizomePayloadDecrypted="Java API fetch Rhizome decrypted payload"
|
||||
setup_RhizomePayloadDecrypted() {
|
||||
setup
|
||||
rhizome_add_bundles $SIDA1 0 1
|
||||
rhizome_add_bundles --encrypted $SIDA1 2 3
|
||||
}
|
||||
test_RhizomePayloadDecrypted() {
|
||||
for n in 0 1 2 3; do
|
||||
executeJavaOk org.servalproject.test.Rhizome rhizome-payload-decrypted "${BID[$n]}" decrypted.bin$n
|
||||
tfw_cat --stdout --stderr
|
||||
assert_metadata $n
|
||||
done
|
||||
for n in 0 1 2 3; do
|
||||
assert cmp file$n decrypted.bin$n
|
||||
done
|
||||
}
|
||||
|
||||
doc_RhizomePayloadDecryptedForeign="Java API cannot fetch foreign Rhizome decrypted payload"
|
||||
setup_RhizomePayloadDecryptedForeign() {
|
||||
setup
|
||||
rhizome_add_bundles --encrypted $SIDA1 0 0
|
||||
set_instance +B
|
||||
create_single_identity
|
||||
rhizome_add_bundles --encrypted $SIDB 1 1
|
||||
executeOk_servald rhizome export manifest "${BID[1]}" file1.manifest
|
||||
set_instance +A
|
||||
executeOk_servald rhizome import bundle raw1 file1.manifest
|
||||
}
|
||||
test_RhizomePayloadDecryptedForeign() {
|
||||
executeJavaOk org.servalproject.test.Rhizome rhizome-payload-decrypted "${BID[1]}" decrypted.bin$n
|
||||
tfw_cat --stdout --stderr
|
||||
assertStdoutGrep RhizomeDecryptionException
|
||||
}
|
||||
|
||||
runTests "$@"
|
||||
|
Loading…
x
Reference in New Issue
Block a user