Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to SBC in KFF (incl. HashPlace) #368

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 1 addition & 6 deletions src/main/java/emissary/core/IBaseDataObjectHelper.java
Expand Up @@ -11,7 +11,6 @@

import java.io.IOException;
import java.lang.reflect.Field;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -173,11 +172,7 @@ public static void addParentInformationToChild(final IBaseDataObject parentIBase
KffDataObjectHandler.parentToChild(childIBaseDataObject);

// Hash the new child data, overwrites parent hashes if any
try {
kffDataObjectHandler.hash(childIBaseDataObject, true);
} catch (NoSuchAlgorithmException | IOException e) {
// Do not add the hash parameters
}
kffDataObjectHandler.hash(childIBaseDataObject);
}

/**
Expand Down
Expand Up @@ -19,6 +19,9 @@
public final class SeekableByteChannelHelper {
private static final Logger logger = LoggerFactory.getLogger(SeekableByteChannelHelper.class);

/** Channel factory backed by an empty byte array. Used for situations when a BDO should have its payload discarded. */
public static final SeekableByteChannelFactory EMPTY_CHANNEL_FACTORY = memory(new byte[0]);

private SeekableByteChannelHelper() {}

/**
Expand Down
89 changes: 27 additions & 62 deletions src/main/java/emissary/kff/KffDataObjectHandler.java
Expand Up @@ -2,6 +2,7 @@

import emissary.core.IBaseDataObject;
import emissary.core.channels.SeekableByteChannelFactory;
import emissary.core.channels.SeekableByteChannelHelper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -67,62 +68,40 @@ public KffDataObjectHandler(boolean truncateKnownData, boolean setFormOnKnownDat
}

/**
* Compute the configure hashes and return as a map Also include entries indicating the know file or duplicate file
* status if so configured
* Convenience memthod to hash a byte array of data.
*
* @param data the bytes to hash
* @param name th name of the data (for reporting)
* @param data to hash
* @param name the name of the data (for reporting)
* @param prefix prepended to hash name entries
* @return parameter entries suitable for a BaseDataObject
* @throws IOException if the data can't be read
* @throws NoSuchAlgorithmException if the checksum can't be computed
*/
public Map<String, String> hashData(byte[] data, String name) {
return hashData(data, name, "");
public Map<String, String> hashData(final byte[] data, final String name, String prefix)
throws IOException, NoSuchAlgorithmException {
return hashData(SeekableByteChannelHelper.memory(data), name, prefix);
}

/**
* Compute the configure hashes and return as a map Also include entries indicating the know file or duplicate file
* status if so configured
*
* @param data the bytes to hash
* @param name th name of the data (for reporting)
* @param prefix prepended to hash name entries
* @param sbcf the data to hash
* @param name the name of the data (for reporting)
* @return parameter entries suitable for a BaseDataObject
* @throws IOException if the data can't be read
* @throws NoSuchAlgorithmException if the checksum can't be computed
*/
public Map<String, String> hashData(@Nullable byte[] data, String name, @Nullable String prefix) {
Map<String, String> results = new HashMap<String, String>();

if (prefix == null) {
prefix = "";
}

if (data != null && data.length > 0) {
try {
KffResult kffCheck = kff.check(name, data);

// Store all computed results in data object params
for (String alg : kffCheck.getResultNames()) {
results.put(prefix + KFF_PARAM_BASE + alg, kffCheck.getResultString(alg));
}

// Set params if we have a hit
if (kffCheck.isKnown()) {
results.put(prefix + KFF_PARAM_KNOWN_FILTER_NAME, kffCheck.getFilterName());
}
if (kffCheck.isDupe()) {
results.put(prefix + KFF_PARAM_DUPE_FILTER_NAME, kffCheck.getFilterName());
}
} catch (Exception kffex) {
logger.warn("Unable to compute kff on " + name, kffex);
}
}
return results;
public Map<String, String> hashData(final SeekableByteChannelFactory sbcf, final String name) throws NoSuchAlgorithmException, IOException {
return hashData(sbcf, name, "");
}

/**
* Compute the configure hashes and return as a map Also include entries indicating the know file or duplicate file
* status if so configured
*
* @param sbcf the data to hash
* @param name th name of the data (for reporting)
* @param name the name of the data (for reporting)
* @param prefix prepended to hash name entries
* @return parameter entries suitable for a BaseDataObject
* @throws IOException if the data can't be read
Expand Down Expand Up @@ -166,22 +145,6 @@ public Map<String, String> hashData(final SeekableByteChannelFactory sbcf, final
* @param d the data object
*/
public void hash(@Nullable final IBaseDataObject d) {
try {
hash(d, false);
} catch (NoSuchAlgorithmException | IOException e) {
// Do nothing
}
}

/**
* Compute the hash of a data object's data
*
* @param d the data object
* @param useSbc use the {@link SeekableByteChannel} interface
* @throws IOException if the data can't be read
* @throws NoSuchAlgorithmException if the checksum can't be computed
*/
public void hash(@Nullable final IBaseDataObject d, final boolean useSbc) throws NoSuchAlgorithmException, IOException {
if (d != null) {
removeHash(d);
}
Expand All @@ -190,13 +153,15 @@ public void hash(@Nullable final IBaseDataObject d, final boolean useSbc) throws
return;
}

// Compute and add the hashes
if (useSbc && d.getChannelSize() > 0) {
d.putParameters(hashData(d.getChannelFactory(), d.shortName(), ""));
} else if (!useSbc && d.dataLength() > 0) {
d.putParameters(hashData(d.data(), d.shortName()));
} else {
return;
try {
// Compute and add the hashes
if (d.getChannelSize() > 0) {
d.putParameters(hashData(d.getChannelFactory(), d.shortName()));
} else {
return;
}
} catch (NoSuchAlgorithmException | IOException e) {
logger.error("Couldn't hash data {}", d.shortName());
}

// Set params if we have a hit
Expand All @@ -208,7 +173,7 @@ public void hash(@Nullable final IBaseDataObject d, final boolean useSbc) throws
d.replaceCurrentForm(KFF_DUPE_CURRENT_FORM);
}
if (truncateKnownData) {
d.setData(null);
d.setChannelFactory(SeekableByteChannelHelper.EMPTY_CHANNEL_FACTORY);
}
}
}
Expand Down
10 changes: 1 addition & 9 deletions src/main/java/emissary/place/KffHashPlace.java
Expand Up @@ -6,7 +6,6 @@

import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;

/**
* Hashing place to hash payload unless hashes are set or skip flag is set. This place is intended to execute in the
Expand All @@ -22,8 +21,6 @@ public class KffHashPlace extends ServiceProviderPlace {

public static final String SKIP_KFF_HASH = "SKIP_KFF_HASH";

private boolean useSbc = false;

public KffHashPlace(String thePlaceLocation) throws IOException {
super(thePlaceLocation);
}
Expand Down Expand Up @@ -51,7 +48,6 @@ public KffHashPlace(InputStream configStream, String placeLocation) throws IOExc
@Override
protected void setupPlace(String theDir, String placeLocation) throws IOException {
super.setupPlace(theDir, placeLocation);
useSbc = configG.findBooleanEntry("USE_SBC", useSbc);
initKff();
}

Expand All @@ -62,11 +58,7 @@ public void process(IBaseDataObject payload) throws ResourceException {
return;
}

try {
kff.hash(payload, useSbc);
} catch (final NoSuchAlgorithmException | IOException e) {
logger.error("KffHashPlace failed to hash data for {} - this shouldn't happen", payload.shortName(), e);
}
kff.hash(payload);
}

}
3 changes: 0 additions & 3 deletions src/main/resources/emissary/place/KffHashPlace.cfg
Expand Up @@ -6,6 +6,3 @@ SERVICE_COST = 10
SERVICE_QUALITY = 100

SERVICE_PROXY = "UNKNOWN"

# Use SeekableByteChannel-related methods (true) vs byte array based (false)
USE_SBC = false
4 changes: 3 additions & 1 deletion src/test/java/emissary/core/IBaseDataObjectHelperTest.java
@@ -1,6 +1,7 @@
package emissary.core;

import emissary.core.channels.InMemoryChannelFactory;
import emissary.core.channels.SeekableByteChannelFactory;
import emissary.kff.KffDataObjectHandler;
import emissary.parser.SessionParser;

Expand Down Expand Up @@ -317,7 +318,8 @@ void testAddParentInformationToChild() throws Exception {
final IBaseDataObject childIbdo1 = new BaseDataObject();

childIbdo1.setChannelFactory(InMemoryChannelFactory.create("0123456789".getBytes(StandardCharsets.US_ASCII)));
Mockito.doThrow(NoSuchAlgorithmException.class).when(mockKffDataObjectHandler1).hash(Mockito.any(BaseDataObject.class), Mockito.anyBoolean());
Mockito.doThrow(NoSuchAlgorithmException.class).when(mockKffDataObjectHandler1).hashData(Mockito.any(SeekableByteChannelFactory.class),
Mockito.anyString());
IBaseDataObjectHelper.addParentInformationToChild(parentIbdo, childIbdo1,
true, alwaysCopyMetadataKeys, placeKey, mockKffDataObjectHandler1);
assertFalse(KffDataObjectHandler.hashPresent(childIbdo1));
Expand Down