<modelVersion>4.0.0</modelVersion>
<groupId>net.pterodactylus</groupId>
<artifactId>jFCPlib</artifactId>
- <version>0.1.3</version>
+ <version>0.1.4</version>
<name>jFCPlib</name>
<packaging>jar</packaging>
<distributionManagement>
<repository>
<id>pterodactylus</id>
<name>pterodactylus.net Maven Repository</name>
- <url>scp://maven@maven.pterodactylus.net/home/maven/repository</url>
+ <url>scpexe://maven@maven.pterodactylus.net/home/maven/repository</url>
</repository>
</distributionManagement>
<dependencies>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
+ <extensions>
+ <extension>
+ <groupId>org.apache.maven.wagon</groupId>
+ <artifactId>wagon-ssh-external</artifactId>
+ <version>2.9</version>
+ </extension>
+ </extensions>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
setField("File", file);
}
+ public AddPeer(String identifier, String file) {
+ this(file);
+ setField("Identifier", identifier);
+ }
+
/**
* Creates a new “AddPeer” request that reads the noderef of the peer from
* the given URL.
setField("URL", String.valueOf(url));
}
+ public AddPeer(String identifier, URL url) {
+ this(url);
+ setField("Identifier", identifier);
+ }
+
/**
* Creates a new “AddPeer” request that adds the peer given by the noderef.
*
setNodeRef(nodeRef);
}
+ public AddPeer(String identifier, NodeRef nodeRef) {
+ this(nodeRef);
+ setField("Identifier", identifier);
+ }
+
//
// PRIVATE METHODS
//
* The noderef of the peer
*/
private void setNodeRef(NodeRef nodeRef) {
- setField("lastGoodVersion", nodeRef.getLastGoodVersion().toString());
+ setField("lastGoodVersion", String.valueOf(nodeRef.getLastGoodVersion()));
setField("opennet", String.valueOf(nodeRef.isOpennet()));
setField("identity", nodeRef.getIdentity());
setField("myName", nodeRef.getMyName());
* @param payloadInputStream
* The payload
*/
- AllData(FcpMessage receivedMessage, InputStream payloadInputStream) {
+ public AllData(FcpMessage receivedMessage, InputStream payloadInputStream) {
super(receivedMessage);
this.payloadInputStream = payloadInputStream;
}
* @return The content of the field, or <code>null</code> if there is no
* such field
*/
- protected String getField(String field) {
+ public String getField(String field) {
return receivedMessage.getField(field);
}
* @see FcpMessage#getFields()
* @return All fields from the message
*/
- protected Map<String, String> getFields() {
+ public Map<String, String> getFields() {
return receivedMessage.getFields();
}
setField("PriorityClass", String.valueOf(priority));
}
+ public void setRealTimeFlag(boolean realTimeFlag) {
+ setField("RealTimeFlag", String.valueOf(realTimeFlag));
+ }
+
/**
* Sets the persistence of the request.
*
* @param receivedMessage
* The received message
*/
- CloseConnectionDuplicateClientName(FcpMessage receivedMessage) {
+ public CloseConnectionDuplicateClientName(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @param receivedMessage
* The received message
*/
- ConfigData(FcpMessage receivedMessage) {
+ public ConfigData(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @param receivedMessage
* The received message
*/
- DataFound(FcpMessage receivedMessage) {
+ public DataFound(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @param fcpMessage
* The received message
*/
- EndListPeerNotes(FcpMessage fcpMessage) {
+ public EndListPeerNotes(FcpMessage fcpMessage) {
super(fcpMessage);
}
* @param receivedMessage
* The message that was received
*/
- EndListPeers(FcpMessage receivedMessage) {
+ public EndListPeers(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @param receivedMessage
* The received message
*/
- EndListPersistentRequests(FcpMessage receivedMessage) {
+ public EndListPersistentRequests(FcpMessage receivedMessage) {
super(receivedMessage);
}
package net.pterodactylus.fcp;
+import java.io.InputStream;
+
/**
* An “CPPluginMessage” sends a message with custom parameters and (optional)
* payload to a plugin.
public class FCPPluginMessage extends FcpMessage {
/**
- * Creates a new “FCPPluginMessage” message for the given plugin.
- *
- * @param pluginClass
- * The name of the plugin class
+ * @deprecated Use {@link #FCPPluginMessage(String, String)} instead
*/
+ @Deprecated
public FCPPluginMessage(String pluginClass) {
super("FCPPluginMessage");
setField("PluginName", pluginClass);
}
+ public FCPPluginMessage(String identifier, String pluginClass) {
+ this(pluginClass);
+ setField("Identifier", identifier);
+ }
+
/**
- * Sets the identifier of the request. Though this is still optional you
- * are encouraged to include it because the plugin might reply in random
- * order to requests.
- *
- * @param identifier
- * The identifier of the request
+ * @deprecated Use {@link #FCPPluginMessage(String, String)} instead
*/
+ @Deprecated
public void setIdentifier(String identifier) {
setField("Identifier", identifier);
}
* Sets a custom parameter for the plugin.
*
* @param key
- * The key of the parameter
+ * The key of the parameter
* @param value
- * The value of the parameter
+ * The value of the parameter
*/
public void setParameter(String key, String value) {
setField("Param." + key, value);
}
/**
- * Sets the length of data of the optional payload. If you call this method
- * you also have to call
- * {@link #setPayloadInputStream(java.io.InputStream)} !
- *
- * @param dataLength
- * The length of data in the payload input stream
+ * @deprecated Use {@link #setData(InputStream, long)} instead
*/
+ @Deprecated
public void setDataLength(long dataLength) {
setField("DataLength", String.valueOf(dataLength));
}
+ public void setData(InputStream payloadInputStream, long dataLength) {
+ setPayloadInputStream(payloadInputStream);
+ setDataLength(dataLength);
+ }
+
}
* @param payloadInputStream
* The optional input stream for the payload
*/
- FCPPluginReply(FcpMessage receivedMessage, InputStream payloadInputStream) {
+ public FCPPluginReply(FcpMessage receivedMessage, InputStream payloadInputStream) {
super(receivedMessage);
this.payloadInputStream = payloadInputStream;
}
/* empty. */
}
+ @Override
+ public void receivedSubscribedUSK(FcpConnection fcpConnection, SubscribedUSK subscribedUSK) {
+ /* empty. */
+ }
+
/**
* {@inheritDoc}
*/
* {@inheritDoc}
*/
@Override
+ public void receivedPluginRemoved(FcpConnection fcpConnection, PluginRemoved pluginRemoved) {
+ /* empty. */
+ }
+
+ @Override
public void receivedFCPPluginReply(FcpConnection fcpConnection, FCPPluginReply fcpPluginReply) {
/* empty. */
}
import java.util.Map;
import java.util.logging.Logger;
+import net.pterodactylus.fcp.FcpUtils.TempInputStream;
+
/**
* An FCP connection to a Freenet node.
*
fcpListenerManager.removeListener(fcpListener);
}
+ public synchronized boolean isClosed() {
+ return connectionHandler == null;
+ }
+
//
// ACTIONS
//
* @param fcpMessage
* The received message
*/
- void handleMessage(FcpMessage fcpMessage) {
+ void handleMessage(FcpMessage fcpMessage) throws IOException{
logger.fine("received message: " + fcpMessage.getName());
String messageName = fcpMessage.getName();
countMessage(messageName);
fcpListenerManager.fireReceivedDataFound(new DataFound(fcpMessage));
} else if ("SubscribedUSKUpdate".equals(messageName)) {
fcpListenerManager.fireReceivedSubscribedUSKUpdate(new SubscribedUSKUpdate(fcpMessage));
+ } else if ("SubscribedUSK".equals(messageName)) {
+ fcpListenerManager.fireReceivedSubscribedUSK(new SubscribedUSK(fcpMessage));
} else if ("IdentifierCollision".equals(messageName)) {
fcpListenerManager.fireReceivedIdentifierCollision(new IdentifierCollision(fcpMessage));
} else if ("AllData".equals(messageName)) {
- LimitedInputStream payloadInputStream = getInputStream(FcpUtils.safeParseLong(fcpMessage.getField("DataLength")));
+ InputStream payloadInputStream = getInputStream(FcpUtils.safeParseLong(fcpMessage.getField("DataLength")));
fcpListenerManager.fireReceivedAllData(new AllData(fcpMessage, payloadInputStream));
- try {
- payloadInputStream.consume();
- } catch (IOException ioe1) {
- /* well, ignore. when the connection handler fails, all fails. */
- }
} else if ("EndListPeerNotes".equals(messageName)) {
fcpListenerManager.fireReceivedEndListPeerNotes(new EndListPeerNotes(fcpMessage));
} else if ("EndListPeers".equals(messageName)) {
} else if ("UnknownNodeIdentifier".equals(messageName)) {
fcpListenerManager.fireReceivedUnknownNodeIdentifier(new UnknownNodeIdentifier(fcpMessage));
} else if ("FCPPluginReply".equals(messageName)) {
- LimitedInputStream payloadInputStream = getInputStream(FcpUtils.safeParseLong(fcpMessage.getField("DataLength")));
+ InputStream payloadInputStream = getInputStream(FcpUtils.safeParseLong(fcpMessage.getField("DataLength")));
fcpListenerManager.fireReceivedFCPPluginReply(new FCPPluginReply(fcpMessage, payloadInputStream));
- try {
- payloadInputStream.consume();
- } catch (IOException ioe1) {
- /* ignore. */
- }
} else if ("PluginInfo".equals(messageName)) {
fcpListenerManager.fireReceivedPluginInfo(new PluginInfo(fcpMessage));
+ } else if ("PluginRemoved".equals(messageName)) {
+ fcpListenerManager.fireReceivedPluginRemoved(new PluginRemoved(fcpMessage));
} else if ("NodeData".equals(messageName)) {
fcpListenerManager.fireReceivedNodeData(new NodeData(fcpMessage));
} else if ("TestDDAReply".equals(messageName)) {
logger.finest("count for " + name + ": " + (oldValue + 1));
}
- /**
- * Returns a limited input stream from the node’s input stream.
- *
- * @param dataLength
- * The length of the stream
- * @return The limited input stream
- */
- private synchronized LimitedInputStream getInputStream(long dataLength) {
- if (dataLength <= 0) {
- return new LimitedInputStream(null, 0);
- }
- return new LimitedInputStream(remoteInputStream, dataLength);
- }
-
- /**
- * A wrapper around an {@link InputStream} that only supplies a limit
- * number of bytes from the underlying input stream.
- *
- * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
- */
- private static class LimitedInputStream extends FilterInputStream {
-
- /** The remaining number of bytes that can be read. */
- private long remaining;
-
- /**
- * Creates a new LimitedInputStream that supplies at most
- * <code>length</code> bytes from the given input stream.
- *
- * @param inputStream
- * The input stream
- * @param length
- * The number of bytes to read
- */
- public LimitedInputStream(InputStream inputStream, long length) {
- super(inputStream);
- remaining = length;
- }
-
- /**
- * @see java.io.FilterInputStream#available()
- */
- @Override
- public synchronized int available() throws IOException {
- if (remaining == 0) {
- return 0;
- }
- return (int) Math.min(super.available(), Math.min(Integer.MAX_VALUE, remaining));
- }
-
- /**
- * @see java.io.FilterInputStream#read()
- */
- @Override
- public synchronized int read() throws IOException {
- int read = -1;
- if (remaining > 0) {
- read = super.read();
- remaining--;
- }
- return read;
- }
-
- /**
- * @see java.io.FilterInputStream#read(byte[], int, int)
- */
- @Override
- public synchronized int read(byte[] b, int off, int len) throws IOException {
- if (remaining == 0) {
- return -1;
- }
- int toCopy = (int) Math.min(len, Math.min(remaining, Integer.MAX_VALUE));
- int read = super.read(b, off, toCopy);
- remaining -= read;
- return read;
- }
-
- /**
- * @see java.io.FilterInputStream#skip(long)
- */
- @Override
- public synchronized long skip(long n) throws IOException {
- if ((n < 0) || (remaining == 0)) {
- return 0;
- }
- long skipped = super.skip(Math.min(n, remaining));
- remaining -= skipped;
- return skipped;
- }
-
- /**
- * {@inheritDoc} This method does nothing, as {@link #mark(int)} and
- * {@link #reset()} are not supported.
- *
- * @see java.io.FilterInputStream#mark(int)
- */
- @Override
- public synchronized void mark(int readlimit) {
- /* do nothing. */
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.io.FilterInputStream#markSupported()
- * @return <code>false</code>
- */
- @Override
- public boolean markSupported() {
- return false;
- }
-
- /**
- * {@inheritDoc} This method does nothing, as {@link #mark(int)} and
- * {@link #reset()} are not supported.
- *
- * @see java.io.FilterInputStream#reset()
- */
- @Override
- public synchronized void reset() throws IOException {
- /* do nothing. */
- }
-
- /**
- * Consumes the input stream, i.e. read all bytes until the limit is
- * reached.
- *
- * @throws IOException
- * if an I/O error occurs
- */
- public synchronized void consume() throws IOException {
- while (remaining > 0) {
- skip(remaining);
- }
- }
-
+ private synchronized InputStream getInputStream(long dataLength) throws IOException {
+ return new TempInputStream(remoteInputStream, dataLength);
}
}
package net.pterodactylus.fcp;
+import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
}
try {
String line = readLine();
- logger.log(Level.FINEST, "read line: %1$s", line);
+ logger.log(Level.FINEST, String.format("read line: %1$s", line));
if (line == null) {
+ throwable = new EOFException();
break;
}
if (line.length() == 0) {
*/
public void receivedPersistentRequestRemoved(FcpConnection fcpConnection, PersistentRequestRemoved persistentRequestRemoved);
+ void receivedSubscribedUSK(FcpConnection fcpConnection, SubscribedUSK subscribedUSK);
+
/**
* Notifies a listener that a “SubscribedUSKUpdate” message was received.
*
*/
public void receivedPluginInfo(FcpConnection fcpConnection, PluginInfo pluginInfo);
+ void receivedPluginRemoved(FcpConnection fcpConnection, PluginRemoved pluginRemoved);
+
/**
* Notifies a listener that an “FCPPluginReply“ message was received.
*
}
}
+ public void fireReceivedSubscribedUSK(SubscribedUSK subscribedUSK) {
+ for (FcpListener fcpListener : getListeners()) {
+ fcpListener.receivedSubscribedUSK(getSource(), subscribedUSK);
+ }
+ }
+
/**
* Notifies all listeners that a “SubscribedUSKUpdate” message was
* received.
}
}
+ public void fireReceivedPluginRemoved(PluginRemoved pluginRemoved) {
+ for (FcpListener fcpListener : getListeners()) {
+ fcpListener.receivedPluginRemoved(getSource(), pluginRemoved);
+ }
+ }
+
/**
* Notifies all listeners that an “FCPPluginReply” message was received.
*
fields.put(field, value);
}
+ public FcpMessage put(String field, String value) {
+ setField(field, value);
+ return this;
+ }
+
/**
* Returns the value of the given field.
*
throw new EOFException("stream reached eof");
}
destination.write(buffer, 0, read);
- remaining -= read;
+ if (remaining > 0) {
+ remaining -= read;
+ }
}
}
* @param receivedMessage
* The message that was recevied
*/
- FinishedCompression(FcpMessage receivedMessage) {
+ public FinishedCompression(FcpMessage receivedMessage) {
super(receivedMessage);
}
--- /dev/null
+package net.pterodactylus.fcp;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Freenet-specific Base64 implementation.
+ *
+ * @author <a href="mailto:bombe@freenetproject.org">David ‘Bombe’ Roden</a>
+ */
+public class FreenetBase64 {
+
+ private static final char[] FREENET_BASE64_ALPHABET =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~-".toCharArray();
+ private static final int[] REVERSE_FREENET_BASE64_ALPHABET = reverse(FREENET_BASE64_ALPHABET);
+
+ private static int[] reverse(char[] alphabet) {
+ String alphabetString = new String(alphabet);
+ int[] reversedAlphabet = new int[128];
+ for (int i = 0; i < 128; i++) {
+ if (alphabetString.indexOf(i) > -1) {
+ reversedAlphabet[i] = alphabetString.indexOf(i);
+ } else {
+ reversedAlphabet[i] = -1;
+ }
+ }
+ return reversedAlphabet;
+ }
+
+ public String encode(byte[] data) {
+ StringBuilder result = new StringBuilder();
+ int currentValue = 0;
+ int index = 0;
+ while (index < data.length) {
+ currentValue = (currentValue << 8) | data[index];
+ if (index % 3 == 2) {
+ result.append(FREENET_BASE64_ALPHABET[(currentValue >> 18) & 0x3f]);
+ result.append(FREENET_BASE64_ALPHABET[(currentValue >> 12) & 0x3f]);
+ result.append(FREENET_BASE64_ALPHABET[(currentValue >> 6) & 0x3f]);
+ result.append(FREENET_BASE64_ALPHABET[currentValue & 0x3f]);
+ }
+ index++;
+ }
+ if (index % 3 == 1) {
+ result.append(FREENET_BASE64_ALPHABET[(currentValue >> 2) & 0x3f]);
+ result.append(FREENET_BASE64_ALPHABET[(currentValue << 4) & 0x3f]);
+ result.append("==");
+ } else if (index % 3 == 2) {
+ result.append(FREENET_BASE64_ALPHABET[(currentValue >> 10) & 0x3f]);
+ result.append(FREENET_BASE64_ALPHABET[(currentValue >> 4) & 0x3f]);
+ result.append(FREENET_BASE64_ALPHABET[(currentValue << 2) & 0x3f]);
+ result.append("=");
+ }
+ return result.toString();
+ }
+
+ public byte[] decode(String data) {
+ ByteArrayOutputStream dataOutput = new ByteArrayOutputStream(data.length() * 3 / 4);
+ try {
+ int currentValue = 0;
+ int index = 0;
+ for (char c : data.toCharArray()) {
+ if (c == '=') {
+ break;
+ }
+ currentValue = (currentValue << 6) | REVERSE_FREENET_BASE64_ALPHABET[c];
+ if (index % 4 == 3) {
+ dataOutput.write((currentValue >> 16) & 0xff);
+ dataOutput.write((currentValue >> 8) & 0xff);
+ dataOutput.write(currentValue & 0xff);
+ }
+ index++;
+ }
+ if (index % 4 == 2) {
+ dataOutput.write((currentValue >> 4) & 0xff);
+ } else if (index % 4 == 3) {
+ dataOutput.write((currentValue >> 10) & 0xff);
+ dataOutput.write((currentValue >> 2) & 0xff);
+ }
+ return dataOutput.toByteArray();
+ } finally {
+ try {
+ dataOutput.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+}
super("GetConfig");
}
+ public GetConfig(String identifer) {
+ this();
+ setField("Identifier", identifer);
+ }
+
/**
* Sets whether the {@link ConfigData} result message shall include the
* current values.
* @param receivedMessage
* The received message
*/
- GetFailed(FcpMessage receivedMessage) {
+ public GetFailed(FcpMessage receivedMessage) {
super(receivedMessage);
}
* <code>true</code> to include volatile data in the noderef
*/
public GetNode(Boolean giveOpennetRef, Boolean withPrivate, Boolean withVolatile) {
+ this(null, giveOpennetRef, withPrivate, withVolatile);
+ }
+
+ public GetNode(String identifier, Boolean giveOpennetRef, Boolean withPrivate, Boolean withVolatile) {
super("GetNode");
+ if (identifier != null) {
+ setField("Identifier", identifier);
+ }
if (giveOpennetRef != null) {
setField("GiveOpennetRef", String.valueOf(giveOpennetRef));
}
*/
public class GetPluginInfo extends FcpMessage {
- /**
- * Creates a new “GetPluginInfo” message.
- *
- * @param pluginName
- * The name of the plugin
- * @param identifier
- * The identifier of the request
- */
- public GetPluginInfo(String pluginName, String identifier) {
+ public GetPluginInfo(String identifier) {
super("GetPluginInfo");
- setField("PluginName", pluginName);
setField("Identifier", identifier);
}
+ public GetPluginInfo(String pluginName, String identifier) {
+ this(identifier);
+ setField("PluginName", pluginName);
+ }
+
+ public void setPluginName(String pluginName) {
+ setField("PluginName", pluginName);
+ }
+
/**
* Sets whether detailed information about the plugin is wanted.
*
* @param receivedMessage
* The received message
*/
- IdentifierCollision(FcpMessage receivedMessage) {
+ public IdentifierCollision(FcpMessage receivedMessage) {
super(receivedMessage);
}
--- /dev/null
+package net.pterodactylus.fcp;
+
+/**
+ * Non-validating wrapper around a Freenet key.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class Key {
+
+ private final String key;
+
+ public Key(String key) {
+ this.key = key;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+}
* The identifier of the node to get details about
*/
public ListPeer(String nodeIdentifier) {
+ this(null, nodeIdentifier);
+ }
+
+ public ListPeer(String identifier, String nodeIdentifier) {
super("ListPeer");
+ if (identifier != null) {
+ setField("Identifier", identifier);
+ }
setField("NodeIdentifier", nodeIdentifier);
}
setField("NodeIdentifier", nodeIdentifier);
}
+ public ListPeerNotes(String identifier, String nodeIdentifier) {
+ this(nodeIdentifier);
+ setField("Identifier", identifier);
+ }
+
}
--- /dev/null
+package net.pterodactylus.fcp;
+
+/**
+ * The “LoadPlugin” message is used to load a plugin.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class LoadPlugin extends FcpMessage {
+
+ public enum UrlType {
+
+ OFFICIAL,
+ FILE,
+ FREENET,
+ URL
+
+ }
+
+ public enum OfficialSource {
+
+ FREENET,
+ HTTPS
+
+ }
+
+ public LoadPlugin(String identifier) {
+ super("LoadPlugin");
+ setField("Identifier", identifier);
+ }
+
+ public void setPluginUrl(String pluginUrl) {
+ setField("PluginURL", pluginUrl);
+ }
+
+ public void setUrlType(UrlType urlType) {
+ setField("URLType", urlType.toString().toLowerCase());
+ }
+
+ public void setStore(boolean store) {
+ setField("Store", String.valueOf(store));
+ }
+
+ public void setOfficialSource(OfficialSource officialSource) {
+ setField("OfficialSource", officialSource.toString().toLowerCase());
+ }
+
+}
super("ModifyConfig");
}
+ public ModifyConfig(String identifier) {
+ this();
+ setField("Identifier", identifier);
+ }
+
/**
* Sets the option with the given name to the given value.
*
*/
public class ModifyPeer extends FcpMessage {
- /**
- * Creates a new “ModifyPeer” request. All Boolean parameters may be null
- * to not influence the current setting.
- *
- * @param nodeIdentifier
- * The identifier of the node, i.e. name, identity, or IP
- * address and port
- * @param allowLocalAddresses
- * Whether to allow local addresses from this node
- * @param disabled
- * Whether the node is disabled
- * @param listenOnly
- * Whether your node should not try to connect the node
- */
+ public ModifyPeer(String identifier, String nodeIdentifier) {
+ super("ModifyPeer");
+ setField("Identifier", identifier);
+ setField("NodeIdentifier", nodeIdentifier);
+ }
+
+ @Deprecated
public ModifyPeer(String nodeIdentifier, Boolean allowLocalAddresses, Boolean disabled, Boolean listenOnly) {
super("ModifyPeer");
setField("NodeIdentifier", nodeIdentifier);
if (allowLocalAddresses != null) {
- setField("AllowLocalAddresses", String.valueOf(allowLocalAddresses));
+ setAllowLocalAddresses(allowLocalAddresses);
}
if (disabled != null) {
- setField("IsDisabled", String.valueOf(disabled));
+ setEnabled(!disabled);
}
if (listenOnly != null) {
- setField("IsListenOnly", String.valueOf(listenOnly));
+ setListenOnly(listenOnly);
}
}
+ public void setAllowLocalAddresses(boolean allowLocalAddresses) {
+ setField("AllowLocalAddresses", String.valueOf(allowLocalAddresses));
+ }
+
+ public void setEnabled(boolean enabled) {
+ setField("IsDisabled", String.valueOf(!enabled));
+ }
+
+ public void setListenOnly(boolean listenOnly) {
+ setField("IsListenOnly", String.valueOf(listenOnly));
+ }
+
+ public void setBurstOnly(boolean burstOnly) {
+ setField("IsBurstOnly", String.valueOf(burstOnly));
+ }
+
+ public void setIgnoreSource(boolean ignoreSource) {
+ setField("IgnoreSourcePort", String.valueOf(ignoreSource));
+ }
+
}
package net.pterodactylus.fcp;
+import com.google.common.base.Charsets;
+
/**
* The “ModifyPeerNote” command modifies a peer note.
*
*/
public class ModifyPeerNote extends FcpMessage {
- /**
- * Creates a new “ModifyPeerNote” request that changes peer note of the
- * given type and node to the given text.
- *
- * @see PeerNote
- * @param nodeIdentifier
- * The identifier of the node, i.e. name, identity, or IP
- * address and port
- * @param noteText
- * The base64-encoded text
- * @param peerNoteType
- * The type of the note to change, possible values are only
- * {@link PeerNote#TYPE_PRIVATE_PEER_NOTE} at the moment
- */
+ private static final FreenetBase64 BASE64_ENCODER = new FreenetBase64();
+
+ public ModifyPeerNote(String identifier, String nodeIdentifier) {
+ super("ModifyPeerNote");
+ setField("Identifier", identifier);
+ setField("NodeIdentifier", nodeIdentifier);
+ }
+
+ @Deprecated
public ModifyPeerNote(String nodeIdentifier, String noteText, int peerNoteType) {
- super("ModifyPeer");
+ super("ModifyPeerNote");
setField("NodeIdentifier", nodeIdentifier);
setField("NoteText", noteText);
setField("PeerNoteType", String.valueOf(peerNoteType));
}
+ public void setNoteText(String noteText) {
+ setField("NoteText", BASE64_ENCODER.encode(noteText.getBytes(Charsets.UTF_8)));
+ }
+
+ public void setPeerNoteType(PeerNoteType peerNoteType) {
+ setField("PeerNoteType", peerNoteType.toString());
+ }
+
}
* @param receivedMessage
* The received message
*/
- NodeData(FcpMessage receivedMessage) {
+ public NodeData(FcpMessage receivedMessage) {
super(receivedMessage);
nodeRef = new NodeRef(receivedMessage);
}
* @param receivedMessage
* The received FCP message
*/
- NodeHello(FcpMessage receivedMessage) {
+ public NodeHello(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @param receivedMessage
* The received message
*/
- Peer(FcpMessage receivedMessage) {
+ public Peer(FcpMessage receivedMessage) {
super(receivedMessage);
}
package net.pterodactylus.fcp;
+import com.google.common.base.Charsets;
+
/**
* The “PeerNote” message contains a private note that has been entered for a
* darknet peer.
*/
public class PeerNote extends BaseMessage {
+ private static final FreenetBase64 BASE64_DECODER = new FreenetBase64();
+
/** The type for base64 encoded peer notes. */
public static final int TYPE_PRIVATE_PEER_NOTE = 1;
* @param receivedMessage
* The received message
*/
- PeerNote(FcpMessage receivedMessage) {
+ public PeerNote(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @return The note text
*/
public String getNoteText() {
- return getField("NoteText");
+ return new String(BASE64_DECODER.decode(getField("NoteText")), Charsets.UTF_8);
}
/**
--- /dev/null
+package net.pterodactylus.fcp;
+
+/**
+ * All possible peer note types.
+ *
+ * @author <a href="mailto:bombe@freenetproject.org">David ‘Bombe’ Roden</a>
+ */
+public enum PeerNoteType {
+
+ PRIVATE_DARKNET_COMMENT(1);
+
+ private int value;
+
+ PeerNoteType(int value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+}
* @param receivedMessage
* The received message
*/
- PeerRemoved(FcpMessage receivedMessage) {
+ public PeerRemoved(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @param receivedMessage
* The received message
*/
- PersistentGet(FcpMessage receivedMessage) {
+ public PersistentGet(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @param receivedMessage
* The received message
*/
- PersistentPut(FcpMessage receivedMessage) {
+ public PersistentPut(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @param receivedMessage
* The received message
*/
- PersistentPutDir(FcpMessage receivedMessage) {
+ public PersistentPutDir(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @param receivedMessage
* The received message
*/
- PersistentRequestModified(FcpMessage receivedMessage) {
+ public PersistentRequestModified(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @param receivedMessage
* The received message
*/
- PersistentRequestRemoved(FcpMessage receivedMessage) {
+ public PersistentRequestRemoved(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @param receivedMessage
* The received message
*/
- PluginInfo(FcpMessage receivedMessage) {
+ public PluginInfo(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @return The original URI of the plugin
*/
public String getOriginalURI() {
- return getField("OriginalUri");
+ return getField("OriginUri");
}
/**
* otherwise
*/
public boolean isStarted() {
- return Boolean.valueOf("Started");
+ return Boolean.valueOf(getField("Started"));
}
+ public boolean isTalkable() {
+ return Boolean.valueOf(getField("IsTalkable"));
+ }
+
+ public String getVersion() {
+ return getField("Version");
+ }
+
+ public String getLongVersion() {
+ return getField("LongVersion");
+ }
}
--- /dev/null
+/*
+ * jFCPlib - PluginInfo.java - Copyright © 2008 David Roden
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package net.pterodactylus.fcp;
+
+/**
+ * The “PluginRemoved” message is a reply to the {@link RemovePlugin} request.
+ *
+ * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
+ */
+public class PluginRemoved extends BaseMessage implements Identifiable {
+
+ /**
+ * Creates a new “PluginRemoved” message that wraps the received message.
+ *
+ * @param receivedMessage
+ * The received message
+ */
+ public PluginRemoved(FcpMessage receivedMessage) {
+ super(receivedMessage);
+ }
+
+ /**
+ * Returns the name of the plugin.
+ *
+ * @return The name of the plugin
+ */
+ public String getPluginName() {
+ return getField("PluginName");
+ }
+
+ /**
+ * Returns the identifier of the request.
+ *
+ * @return The identifier of the request
+ */
+ @Override
+ public String getIdentifier() {
+ return getField("Identifier");
+ }
+
+}
* @param receivedMessage
* The received message
*/
- ProtocolError(FcpMessage receivedMessage) {
+ public ProtocolError(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @param receivedMessage
* The received message
*/
- PutFailed(FcpMessage receivedMessage) {
+ public PutFailed(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @param receivedMessage
* The received message
*/
- PutFetchable(FcpMessage receivedMessage) {
+ public PutFetchable(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @param receivedMessage
* The received message
*/
- PutSuccessful(FcpMessage receivedMessage) {
+ public PutSuccessful(FcpMessage receivedMessage) {
super(receivedMessage);
}
--- /dev/null
+package net.pterodactylus.fcp;
+
+/**
+ * The “ReloadPlugin” message is used to reload a plugin.
+ *
+ * @author <a href="mailto:bombe@freenetproject.org">David ‘Bombe’ Roden</a>
+ */
+public class ReloadPlugin extends FcpMessage {
+
+ public ReloadPlugin(String identifier) {
+ super("ReloadPlugin");
+ setField("Identifier", identifier);
+ }
+
+ public void setPluginName(String pluginName) {
+ setField("PluginName", pluginName);
+ }
+
+ public void setMaxWaitTime(int maxWaitTime) {
+ setField("MaxWaitTime", String.valueOf(maxWaitTime));
+ }
+
+ public void setPurge(boolean purge) {
+ setField("Purge", String.valueOf(purge));
+ }
+
+ public void setStore(boolean store) {
+ setField("Store", String.valueOf(store));
+ }
+
+}
*/
public class RemovePeer extends FcpMessage {
- /**
- * Creates a new “RemovePeer” command that removes the given peer.
- *
- * @param nodeIdentifier
- * The identifier of the node, i.e. its name, identity, or IP
- * address and port pair
- */
+ @Deprecated
public RemovePeer(String nodeIdentifier) {
super("RemovePeer");
setField("NodeIdentifier", nodeIdentifier);
}
+ public RemovePeer(String identifier, String nodeIdentifier) {
+ this(nodeIdentifier);
+ setField("Identifier", identifier);
+ }
+
}
--- /dev/null
+package net.pterodactylus.fcp;
+
+/**
+ * The “RemovePlugin” message is used to remove a plugin.
+ *
+ * @author <a href="mailto:bombe@freenetproject.org">David ‘Bombe’ Roden</a>
+ */
+public class RemovePlugin extends FcpMessage {
+
+ public RemovePlugin(String identifier) {
+ super("RemovePlugin");
+ setField("Identifier", identifier);
+ }
+
+ public void setPluginName(String pluginName) {
+ setField("PluginName", pluginName);
+ }
+
+ public void setMaxWaitTime(int maxWaitTime) {
+ setField("MaxWaitTime", String.valueOf(maxWaitTime));
+ }
+
+ public void setPurge(boolean purge) {
+ setField("Purge", String.valueOf(purge));
+ }
+
+}
--- /dev/null
+package net.pterodactylus.fcp;
+
+/**
+ * Progress information about a request.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class RequestProgress {
+
+ private final int total;
+ private final int required;
+ private final int failed;
+ private final int fatallyFailed;
+ private final long lastProgress;
+ private final int succeeded;
+ private final boolean finalizedTotal;
+ private final int minSuccessFetchBlocks;
+
+ public RequestProgress(int total, int required, int failed, int fatallyFailed, long lastProgress, int succeeded,
+ boolean finalizedTotal, int minSuccessFetchBlocks) {
+ this.total = total;
+ this.required = required;
+ this.failed = failed;
+ this.fatallyFailed = fatallyFailed;
+ this.lastProgress = lastProgress;
+ this.succeeded = succeeded;
+ this.finalizedTotal = finalizedTotal;
+ this.minSuccessFetchBlocks = minSuccessFetchBlocks;
+ }
+
+ public int getTotal() {
+ return total;
+ }
+
+ public int getRequired() {
+ return required;
+ }
+
+ public int getFailed() {
+ return failed;
+ }
+
+ public int getFatallyFailed() {
+ return fatallyFailed;
+ }
+
+ public long getLastProgress() {
+ return lastProgress;
+ }
+
+ public int getSucceeded() {
+ return succeeded;
+ }
+
+ public boolean isFinalizedTotal() {
+ return finalizedTotal;
+ }
+
+ public int getMinSuccessFetchBlocks() {
+ return minSuccessFetchBlocks;
+ }
+
+}
* @param receivedMessage
* The received message
*/
- SSKKeypair(FcpMessage receivedMessage) {
+ public SSKKeypair(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @param receivedMessage
* The received message
*/
- SimpleProgress(FcpMessage receivedMessage) {
+ public SimpleProgress(FcpMessage receivedMessage) {
super(receivedMessage);
}
return Boolean.valueOf(getField("FinalizedTotal"));
}
+ public long getLastProgress() {
+ return Long.valueOf(getField("LastProgress"));
+ }
+
+ public int getMinSuccessFetchBlocks() {
+ return Integer.valueOf(getField("MinSuccessFetchBlocks"));
+ }
+
/**
* Returns the identifier of the request.
*
* @param receivedMessage
* The received message
*/
- StartedCompression(FcpMessage receivedMessage) {
+ public StartedCompression(FcpMessage receivedMessage) {
super(receivedMessage);
}
*
* @author David ‘Bombe’ Roden <bombe@freenetproject.org>
*/
-public class SubscribeUSK extends FcpMessage {
+public class SubscribeUSK extends FcpMessage implements Identifiable {
- /**
- * Creates a new “SubscribeUSK” message.
- *
- * @param uri
- * The URI to watch for changes
- * @param identifier
- * The identifier of the request
- */
- public SubscribeUSK(String uri, String identifier) {
+ public SubscribeUSK(String identifier) {
super("SubscribeUSK");
- setField("URI", uri);
setField("Identifier", identifier);
}
+ public SubscribeUSK(String uri, String identifier) {
+ this(identifier);
+ setField("URI", uri);
+ }
+
+ @Override
+ public String getIdentifier() {
+ return getField("Identifier");
+ }
+
+ public String getUri() {
+ return getField("URI");
+ }
+
+ public void setUri(String uri) {
+ setField("URI", uri);
+ }
+
+ public boolean isActive() {
+ return !Boolean.parseBoolean(getField("DontPoll"));
+ }
+
/**
* Sets whether updates for the USK are actively searched.
*
setField("DontPoll", String.valueOf(!active));
}
+ public boolean isSparse() {
+ return Boolean.valueOf(getField("SparsePoll"));
+ }
+
+ public void setSparse(boolean sparse) {
+ setField("SparsePoll", String.valueOf(sparse));
+ }
+
+ public Priority getPriority() {
+ String priorityClass = getField("PriorityClass");
+ if (priorityClass != null) {
+ return Priority.valueOf(priorityClass);
+ }
+ return Priority.bulkSplitfile;
+ }
+
+ public void setPriority(Priority priority) {
+ setField("PriorityClass", priority.toString());
+ }
+
+ public Priority getActivePriority() {
+ String priorityClass = getField("PriorityClassProgress");
+ if (priorityClass != null) {
+ return Priority.valueOf(priorityClass);
+ }
+ return Priority.update;
+ }
+
+ public void setActivePriority(Priority activePriority) {
+ setField("PriorityClassProgress", activePriority.toString());
+ }
+
+ public boolean isRealTime() {
+ return Boolean.valueOf(getField("RealTimeFlag"));
+ }
+
+ public void setRealTime(boolean realTime) {
+ setField("RealTimeFlag", String.valueOf(realTime));
+ }
+
+ public boolean isIgnoreDateHints() {
+ return Boolean.valueOf(getField("IgnoreUSKDatehints"));
+ }
+
+ public void setIgnoreDateHints(boolean ignoreDateHints) {
+ setField("IgnoreUSKDatehints", String.valueOf(ignoreDateHints));
+ }
+
}
--- /dev/null
+/*
+ * jFCPlib - SubscribedUSKUpdate.java - Copyright © 2008 David Roden
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package net.pterodactylus.fcp;
+
+/**
+ * A “SubscribedUSK” message is sent when a {@link SubscribeUSK} was succesfully processed.
+ *
+ * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
+ */
+public class SubscribedUSK extends BaseMessage implements Identifiable {
+
+ public SubscribedUSK(FcpMessage receivedMessage) {
+ super(receivedMessage);
+ }
+
+ @Override
+ public String getIdentifier() {
+ return getField("Identifier");
+ }
+
+ public String getURI() {
+ return getField("URI");
+ }
+
+ public boolean isDontPoll() {
+ return Boolean.parseBoolean(getField("DontPoll"));
+ }
+
+}
* @param receivedMessage
* The received message
*/
- SubscribedUSKUpdate(FcpMessage receivedMessage) {
+ public SubscribedUSKUpdate(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @param receivedMessage
* The received message
*/
- TestDDAComplete(FcpMessage receivedMessage) {
+ public TestDDAComplete(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @param receivedMessage
* The received message
*/
- TestDDAReply(FcpMessage receivedMessage) {
+ public TestDDAReply(FcpMessage receivedMessage) {
super(receivedMessage);
}
*/
public TestDDAResponse(String directory, String readContent) {
super("TestDDAResponse");
+ setField("Directory", directory);
if (readContent != null) {
setField("ReadContent", readContent);
}
* @param receivedMessage
* The received message
*/
- URIGenerated(FcpMessage receivedMessage) {
+ public URIGenerated(FcpMessage receivedMessage) {
super(receivedMessage);
}
* @param receivedMessage
* The received message
*/
- UnknownNodeIdentifier(FcpMessage receivedMessage) {
+ public UnknownNodeIdentifier(FcpMessage receivedMessage) {
super(receivedMessage);
}
--- /dev/null
+package net.pterodactylus.fcp;
+
+/**
+ * The “UnsubscribeUSK” message is used to cancel a {@link SubscribeUSK USK subscription}.
+ *
+ * @author <a href="mailto:bombe@freenetproject.org">David ‘Bombe’ Roden</a>
+ */
+public class UnsubscribeUSK extends FcpMessage {
+
+ public UnsubscribeUSK(String identifier) {
+ super("UnsubscribeUSK");
+ setField("Identifier", identifier);
+ }
+
+}
--- /dev/null
+package net.pterodactylus.fcp;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+import org.junit.Test;
+
+/**
+ * Unit test for {@link ModifyPeerNote}.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class ModifyPeerNoteTest {
+
+ private static final String IDENTIFIER = "identifier";
+ private static final String NODE_IDENTIFIER = "node_identifier";
+ private static final String ENCODED_NOTE_TEXT = "VWJlck5vZGUgKHVudGlsIEkgaGF2ZSByZWFsIHBlZXJzKQ==";
+ private static final String DECODED_NOTE_TEXT = "UberNode (until I have real peers)";
+
+ @Test
+ public void noteTextIsEncodedCorrectly() {
+ ModifyPeerNote modifyPeerNote = new ModifyPeerNote(IDENTIFIER, NODE_IDENTIFIER);
+ modifyPeerNote.setNoteText(DECODED_NOTE_TEXT);
+ assertThat(modifyPeerNote.getField("NoteText"), is(ENCODED_NOTE_TEXT));
+ }
+
+
+}
--- /dev/null
+package net.pterodactylus.fcp;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+import org.junit.Test;
+
+/**
+ * Unit test for {@link PeerNote}.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class PeerNoteTest {
+
+ @Test
+ public void peerNoteIsDecodedCorrectly() {
+ FcpMessage receivedMessage = new FcpMessage("PeerNote");
+ receivedMessage.setField("NoteText", "VWJlck5vZGUgKHVudGlsIEkgaGF2ZSByZWFsIHBlZXJzKQ==");
+ PeerNote peerNote = new PeerNote(receivedMessage);
+ assertThat(peerNote.getNoteText(), is("UberNode (until I have real peers)"));
+ }
+
+}