package plugins.CENO.FreenetInterface;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import plugins.CENO.FreenetInterface.ConnectionOverview.NodeConnections;
import freenet.client.ClientMetadata;
import freenet.client.DefaultMIMETypes;
import freenet.client.FetchContext;
import freenet.client.FetchException;
import freenet.client.FetchException.FetchExceptionMode;
import freenet.client.FetchResult;
import freenet.client.InsertBlock;
import freenet.client.InsertContext;
import freenet.client.InsertException;
import freenet.client.async.BaseClientPutter;
import freenet.client.async.ClientContext;
import freenet.client.async.ClientGetCallback;
import freenet.client.async.ClientGetter;
import freenet.client.async.ClientPutCallback;
import freenet.client.async.PersistenceDisabledException;
import freenet.client.async.USKCallback;
import freenet.keys.FreenetURI;
import freenet.keys.InsertableClientSSK;
import freenet.keys.USK;
import freenet.node.Node;
import freenet.node.RequestClient;
import freenet.node.RequestStarter;
import freenet.pluginmanager.PluginRespirator;
import freenet.support.Logger;
import freenet.support.api.Bucket;
import freenet.support.api.RandomAccessBucket;
import freenet.support.io.ResumeFailedException;
public class NodeInterface implements FreenetInterface {
private Node node;
private FetchContext ULPRFC, localFC, distFC;
private ConnectionOverview connectionOverview;
public NodeInterface(Node node, PluginRespirator pr) {
this.node = node;
new HighLevelSimpleClientInterface(node);
this.connectionOverview = new ConnectionOverview(node);
initFetchContexts();
}
private void initFetchContexts() {
// Set up a FetchContext instance for Ultra-lightweight passive requests
this.ULPRFC = HighLevelSimpleClientInterface.getFetchContext();
this.ULPRFC.canWriteClientCache = true;
this.ULPRFC.maxNonSplitfileRetries = -1;
this.ULPRFC.followRedirects = true;
this.ULPRFC.allowSplitfiles = true;
this.ULPRFC.maxRecursionLevel = 10;
this.ULPRFC.maxTempLength = Long.MAX_VALUE;
this.ULPRFC.maxOutputLength = Long.MAX_VALUE;
// Set up a FetchContext instance for lookup requests in the local cache only
this.localFC = HighLevelSimpleClientInterface.getFetchContext();
this.localFC.localRequestOnly = true;
this.localFC.followRedirects = true;
this.localFC.allowSplitfiles = true;
this.localFC.maxRecursionLevel = 10;
this.localFC.maxTempLength = Long.MAX_VALUE;
this.localFC.maxOutputLength = Long.MAX_VALUE;
// Set up a FetchContext instance for lookup requests in the distributed cache only
this.distFC = HighLevelSimpleClientInterface.getFetchContext();
this.distFC.ignoreStore = true;
this.distFC.canWriteClientCache = true;
this.distFC.followRedirects = true;
this.distFC.allowSplitfiles = true;
this.distFC.maxRecursionLevel = 10;
this.distFC.maxTempLength = Long.MAX_VALUE;
this.distFC.maxOutputLength = Long.MAX_VALUE;
}
@Override
public FetchResult fetchURI(FreenetURI uri) throws FetchException {
return HighLevelSimpleClientInterface.fetchURI(uri);
}
@Override
public ClientGetter localFetchURI(FreenetURI uri, ClientGetCallback callback) throws FetchException {
return HighLevelSimpleClientInterface.fetchURI(uri, Long.MAX_VALUE, callback, localFC);
}
@Override
public ClientGetter distFetchURI(FreenetURI uri, ClientGetCallback callback) throws FetchException {
return HighLevelSimpleClientInterface.fetchURI(uri, Long.MAX_VALUE, callback, distFC);
}
@Override
public ClientGetter fetchULPR(FreenetURI uri, ClientGetCallback callback) throws FetchException {
return HighLevelSimpleClientInterface.fetchURI(uri, Long.MAX_VALUE, callback, ULPRFC);
}
@Override
public boolean subscribeToUSK(USK origUSK, USKCallback cb) {
node.clientCore.uskManager.subscribe(origUSK, cb, false, getRequestClient());
return true;
}
/**
* Generate a new key pair for SSK insertions
*
* @return FreenetURI array where first element is the insertURI and second element is the requestURI
*/
@Override
public FreenetURI[] generateKeyPair() {
InsertableClientSSK key = InsertableClientSSK.createRandom(node.random, "");
FreenetURI insertURI = key.getInsertURI();
FreenetURI requestURI = key.getURI();
return new FreenetURI[]{insertURI, requestURI};
}
@Override
public RequestClient getRequestClient() {
return HighLevelSimpleClientInterface.getRequestClient();
}
@Override
public Bucket makeBucket(int length) throws IOException {
return node.clientCore.persistentTempBucketFactory.makeBucket(length);
}
@Override
public FreenetURI insertBundleManifest(FreenetURI insertURI, String content, String defaultName, ClientPutCallback insertCb) throws IOException, InsertException {
String defName;
if (defaultName == null || defaultName.isEmpty()) {
defName = "default.html";
} else {
defName = defaultName;
}
Bucket bucket = HighLevelSimpleClientInterface.getBucketFromString(content);
HashMap<String, Object> bucketsByName = new HashMap<String, Object>();
bucketsByName.put(defName, bucket);
FreenetURI requestURI = HighLevelSimpleClientInterface.insertManifestCb(insertURI, bucketsByName, defName, RequestStarter.INTERACTIVE_PRIORITY_CLASS, null, insertCb);
return requestURI;
}
@Override
public boolean insertFreesite(FreenetURI insertURI, String docName, String content, ClientPutCallback insertCallback) throws IOException, InsertException {
String mimeType = DefaultMIMETypes.guessMIMEType(docName, true);
if(mimeType == null) {
mimeType = "text/html";
}
RandomAccessBucket bucket = (RandomAccessBucket) HighLevelSimpleClientInterface.getBucketFromString(content);
InsertBlock ib = new InsertBlock(bucket, new ClientMetadata(mimeType), insertURI);
InsertContext ictx = HighLevelSimpleClientInterface.getInsertContext(true);
HighLevelSimpleClientInterface.insert(ib, docName, false, ictx, insertCallback, RequestStarter.INTERACTIVE_PRIORITY_CLASS);
return true;
}
@Override
public FreenetURI insertBlock(InsertBlock insert, boolean getCHKOnly, String filenameHint) throws InsertException {
return HighLevelSimpleClientInterface.insert(insert, getCHKOnly, filenameHint);
}
@Override
public FreenetURI insertManifest(FreenetURI insertURI, HashMap<String, Object> bucketsByName, String defaultName, short priorityClass) throws InsertException {
return HighLevelSimpleClientInterface.insertManifest(insertURI, bucketsByName, defaultName, priorityClass);
}
@Override
public FreenetURI insertSingleChunk(FreenetURI uri, String content, ClientPutCallback cb) throws InsertException, PersistenceDisabledException, UnsupportedEncodingException {
return HighLevelSimpleClientInterface.insertSingleChunk(uri, content, cb);
}
@Override
public FreenetURI insertSingleChunk(FreenetURI uri, byte[] content, ClientPutCallback cb) throws InsertException, PersistenceDisabledException, UnsupportedEncodingException {
return HighLevelSimpleClientInterface.insertSingleChunk(uri, content, cb);
}
@Override
public NodeConnections getConnections() {
return connectionOverview.getConnections();
}
@Override
public ClientGetCallback getVoidGetCallback(String successMessage, String failureMessage, NewURICallback onNewURI) {
return new VoidGetCallback(successMessage, failureMessage, getRequestClient(), onNewURI);
}
@Override
public ClientPutCallback getVoidPutCallback(String successMessage, String failureMessage) {
return new VoidPutCallback(successMessage, failureMessage, getRequestClient());
}
private class VoidPutCallback implements ClientPutCallback {
String successMessage, failureMessage = null;
RequestClient reqClient;
public VoidPutCallback(String successMessage, String failureMessage, RequestClient reqClient) {
this.successMessage = successMessage;
this.failureMessage = failureMessage;
this.reqClient = reqClient;
}
@Override
public void onResume(ClientContext context) throws ResumeFailedException {
}
@Override
public RequestClient getRequestClient() {
return reqClient;
}
@Override
public void onGeneratedURI(FreenetURI uri, BaseClientPutter state) {
}
@Override
public void onGeneratedMetadata(Bucket metadata, BaseClientPutter state) {
}
@Override
public void onFetchable(BaseClientPutter state) {
}
@Override
public void onSuccess(BaseClientPutter state) {
Logger.normal(this, successMessage);
}
@Override
public void onFailure(InsertException e, BaseClientPutter state) {
Logger.error(this, failureMessage + ": " + e.getMessage());
}
}
private class VoidGetCallback implements ClientGetCallback {
String successMessage, failureMessage = null;
RequestClient reqClient;
NewURICallback onNewURI;
public VoidGetCallback(String successMessage, String failureMessage, RequestClient reqClient, NewURICallback onNewURI) {
this.successMessage = successMessage;
this.failureMessage = failureMessage;
this.reqClient = reqClient;
this.onNewURI = onNewURI;
}
@Override
public void onResume(ClientContext context) throws ResumeFailedException {
}
@Override
public RequestClient getRequestClient() {
return reqClient;
}
@Override
public void onSuccess(FetchResult result, ClientGetter state) {
Logger.normal(this, successMessage);
}
@Override
public void onFailure(FetchException e, ClientGetter state) {
if (e.getMode() == FetchExceptionMode.PERMANENT_REDIRECT) {
try {
onNewURI.handleNewURI(e.newURI, successMessage, failureMessage);
return;
} catch (FetchException e1) {
Logger.error(this, "Permanent redirect but fetchexception: " +e1.getMessage());
}
}
Logger.error(this, failureMessage + ": " + e.getMessage());
}
}
public interface NewURICallback {
void handleNewURI(FreenetURI newURI, String successMessage, String failureMessage) throws FetchException;
}
}