--- /dev/null
+/**
+ * © 2008 INA Service GmbH
+ */
+package net.pterodactylus.util.fcp.message;
+
+import java.security.interfaces.DSAParams;
+import java.util.StringTokenizer;
+
+import net.pterodactylus.util.fcp.FcpMessage;
+import net.pterodactylus.util.fcp.FcpUtils;
+
+/**
+ * The “Peer” reply by the node contains information about a peer.
+ *
+ * @author <a href="mailto:dr@ina-germany.de">David Roden</a>
+ * @version $Id$
+ */
+public class Peer extends BaseMessage {
+
+ /**
+ * Creates a new “Peer” reply from the received message.
+ *
+ * @param receivedMessage
+ * The received message
+ */
+ public Peer(FcpMessage receivedMessage) {
+ super(receivedMessage);
+ }
+
+ /**
+ * Returns the “physical.udp” line from the message. It contains all IP
+ * addresses and port numbers of the peer.
+ *
+ * @return The IP addresses and port numbers of the peer
+ */
+ public String getPhysicalUDP() {
+ return getField("physical.udp");
+ }
+
+ /**
+ * Returns whether the listed peer is an opennet peer.
+ *
+ * @return <code>true</code> if the peer is an opennet peer,
+ * <code>false</code> if the peer is a darknet peer
+ */
+ public boolean isOpennet() {
+ return Boolean.valueOf(getField("opennet"));
+ }
+
+ /**
+ * Returns the “y” part of the peer’s public DSA key.
+ *
+ * @return The public DSA key
+ */
+ public String getDSAPublicKey() {
+ return getField("dsaPubKey.y");
+ }
+
+ /**
+ * Returns the DSA group of the peer.
+ *
+ * @return The DSA group of the peer
+ */
+ public DSAGroup getDSAGroup() {
+ return new DSAGroup(getField("dsaGroup.g"), getField("dsaGroup.p"), getField("dsaGroup.q"));
+ }
+
+ /**
+ * Returns the last good version of the peer, i.e. the oldest version the
+ * peer will connect to.
+ *
+ * @return The last good version of the peer
+ */
+ public Version getLastGoodVersion() {
+ return new Version(getField("lastGoodVersion"));
+ }
+
+ /**
+ * Returns the ARK of the peer.
+ *
+ * @return The ARK of the peer
+ */
+ public ARK getARK() {
+ return new ARK(getField("ark.pubURI"), getField("ark.number"));
+ }
+
+ /**
+ * Returns the identity of the peer.
+ *
+ * @return The identity of the peer
+ */
+ public String getIdentity() {
+ return getField("identity");
+ }
+
+ /**
+ * Returns the name of the peer. If the peer is not a darknet peer it will
+ * have no name.
+ *
+ * @return The name of the peer, or <code>null</code> if the peer is an
+ * opennet peer
+ */
+ public String getMyName() {
+ return getField("myName");
+ }
+
+ /**
+ * Returns the location of the peer.
+ *
+ * @return The location of the peer
+ * @throws NumberFormatException
+ * if the field can not be parsed
+ */
+ public double getLocation() throws NumberFormatException {
+ return Double.valueOf(getField("location"));
+ }
+
+ /**
+ * Returns whether the peer is a testnet node.
+ *
+ * @return <code>true</code> if the peer is a testnet node,
+ * <code>false</code> otherwise
+ */
+ public boolean isTestnet() {
+ return Boolean.valueOf("testnet");
+ }
+
+ /**
+ * Returns the version of the peer.
+ *
+ * @return The version of the peer
+ */
+ public Version getVersion() {
+ return new Version(getField("version"));
+ }
+
+ /**
+ * Returns the negotiation types the peer supports.
+ *
+ * @return The supported negotiation types
+ */
+ public int[] getNegotiationTypes() {
+ return FcpUtils.parseMultiIntegerField(getField("auth.negTypes"));
+ }
+
+ /**
+ * Container for the “lastGoodVersion” field.
+ *
+ * @author <a href="mailto:dr@ina-germany.de">David Roden</a>
+ * @version $Id$
+ */
+ public static class Version {
+
+ /** The name of the node implementation. */
+ private final String nodeName;
+
+ /** The tree version of the node. */
+ private final String treeVersion;
+
+ /** The protocol version of the node. */
+ private final String protocolVersion;
+
+ /** The build number of the node. */
+ private final int buildNumber;
+
+ /**
+ * Creates a new Version from the given string. The string consists of
+ * the four required fields node name, tree version, protocol version,
+ * and build number, separated by a comma.
+ *
+ * @param version
+ * The version string
+ * @throws NullPointerException
+ * if <code>version</code> is <code>null</code>
+ * @throws IllegalArgumentException
+ * if <code>version</code> is not in the right format
+ */
+ public Version(String version) {
+ if (version == null) {
+ throw new NullPointerException("version must not be null");
+ }
+ StringTokenizer versionTokens = new StringTokenizer(version, ",");
+ if (versionTokens.countTokens() != 4) {
+ throw new IllegalArgumentException("version must consist of four fields");
+ }
+ this.nodeName = versionTokens.nextToken();
+ this.treeVersion = versionTokens.nextToken();
+ this.protocolVersion = versionTokens.nextToken();
+ try {
+ this.buildNumber = Integer.valueOf(versionTokens.nextToken());
+ } catch (NumberFormatException nfe1) {
+ throw new IllegalArgumentException("last part of version must be numeric", nfe1);
+ }
+ }
+
+ /**
+ * Creates a new Version from the given parts.
+ *
+ * @param nodeName
+ * The name of the node implementation
+ * @param treeVersion
+ * The tree version
+ * @param protocolVersion
+ * The protocol version
+ * @param buildNumber
+ * The build number of the node
+ */
+ public Version(String nodeName, String treeVersion, String protocolVersion, int buildNumber) {
+ this.nodeName = nodeName;
+ this.treeVersion = treeVersion;
+ this.protocolVersion = protocolVersion;
+ this.buildNumber = buildNumber;
+ }
+
+ /**
+ * Returns the name of the node implementation.
+ *
+ * @return The node name
+ */
+ public String getNodeName() {
+ return nodeName;
+ }
+
+ /**
+ * The tree version of the node.
+ *
+ * @return The tree version of the node
+ */
+ public String getTreeVersion() {
+ return treeVersion;
+ }
+
+ /**
+ * The protocol version of the node
+ *
+ * @return The protocol version of the node
+ */
+ public String getProtocolVersion() {
+ return protocolVersion;
+ }
+
+ /**
+ * The build number of the node.
+ *
+ * @return The build number of the node
+ */
+ public int getBuildNumber() {
+ return buildNumber;
+ }
+
+ }
+
+ /**
+ * Container for ARKs (address resolution keys).
+ *
+ * @author <a href="mailto:dr@ina-germany.de">David Roden</a>
+ * @version $Id$
+ */
+ public static class ARK {
+
+ /** The public URI of the ARK. */
+ private final String publicURI;
+
+ /** The number of the ARK. */
+ private final int number;
+
+ /**
+ * Creates a new ARK with the given URI and number.
+ *
+ * @param publicURI
+ * The public URI of the ARK
+ * @param number
+ * The number of the ARK
+ */
+ public ARK(String publicURI, String number) {
+ if ((publicURI == null) || (number == null)) {
+ throw new NullPointerException(((publicURI == null) ? "publicURI" : "number") + " must not be null");
+ }
+ this.publicURI = publicURI;
+ try {
+ this.number = Integer.valueOf(number);
+ } catch (NumberFormatException nfe1) {
+ throw new IllegalArgumentException("number must be numeric", nfe1);
+ }
+ }
+
+ /**
+ * Returns the public URI of the ARK.
+ *
+ * @return The public URI of the ARK
+ */
+ public String getPublicURI() {
+ return publicURI;
+ }
+
+ /**
+ * Returns the number of the ARK.
+ *
+ * @return The number of the ARK
+ */
+ public int getNumber() {
+ return number;
+ }
+
+ }
+
+ /**
+ * Container for the DSA group of a peer. A DSA group consists of a base
+ * (called “g”), a prime (called “p”) and a subprime (called “q”).
+ *
+ * @see DSAParams
+ * @author <a href="mailto:dr@ina-germany.de">David Roden</a>
+ * @version $Id$
+ */
+ public static class DSAGroup {
+
+ /** The base of the DSA group. */
+ private final String base;
+
+ /** The prime of the DSA group. */
+ private final String prime;
+
+ /** The subprime of the DSA group. */
+ private final String subprime;
+
+ /**
+ * Creates a new DSA group with the given base (“g”), prime (“p”), and
+ * subprime (“q”).
+ *
+ * @param base
+ * The base of the DSA group
+ * @param prime
+ * The prime of the DSA group
+ * @param subprime
+ * The subprime of the DSA group
+ */
+ public DSAGroup(String base, String prime, String subprime) {
+ this.base = base;
+ this.prime = prime;
+ this.subprime = subprime;
+ }
+
+ /**
+ * Returns the base (“g”) of the DSA group.
+ *
+ * @return The base of the DSA group
+ */
+ public String getBase() {
+ return base;
+ }
+
+ /**
+ * Returns the prime (“p”) of the DSA group.
+ *
+ * @return The prime of the DSA group
+ */
+ public String getPrime() {
+ return prime;
+ }
+
+ /**
+ * Returns the subprime (“q”) of the DSA group.
+ *
+ * @return The subprime of the DSA group
+ */
+ public String getSubprime() {
+ return subprime;
+ }
+
+ }
+
+}