2 * © 2008 INA Service GmbH
4 package net.pterodactylus.util.fcp.message;
6 import java.security.interfaces.DSAParams;
7 import java.util.StringTokenizer;
9 import net.pterodactylus.util.fcp.FcpMessage;
10 import net.pterodactylus.util.fcp.FcpUtils;
13 * The “Peer” reply by the node contains information about a peer.
15 * @author <a href="mailto:dr@ina-germany.de">David Roden</a>
18 public class Peer extends BaseMessage {
21 * Creates a new “Peer” reply from the received message.
23 * @param receivedMessage
24 * The received message
26 public Peer(FcpMessage receivedMessage) {
27 super(receivedMessage);
31 * Returns the “physical.udp” line from the message. It contains all IP
32 * addresses and port numbers of the peer.
34 * @return The IP addresses and port numbers of the peer
36 public String getPhysicalUDP() {
37 return getField("physical.udp");
41 * Returns whether the listed peer is an opennet peer.
43 * @return <code>true</code> if the peer is an opennet peer,
44 * <code>false</code> if the peer is a darknet peer
46 public boolean isOpennet() {
47 return Boolean.valueOf(getField("opennet"));
51 * Returns the “y” part of the peer’s public DSA key.
53 * @return The public DSA key
55 public String getDSAPublicKey() {
56 return getField("dsaPubKey.y");
60 * Returns the DSA group of the peer.
62 * @return The DSA group of the peer
64 public DSAGroup getDSAGroup() {
65 return new DSAGroup(getField("dsaGroup.g"), getField("dsaGroup.p"), getField("dsaGroup.q"));
69 * Returns the last good version of the peer, i.e. the oldest version the
70 * peer will connect to.
72 * @return The last good version of the peer
74 public Version getLastGoodVersion() {
75 return new Version(getField("lastGoodVersion"));
79 * Returns the ARK of the peer.
81 * @return The ARK of the peer
84 return new ARK(getField("ark.pubURI"), getField("ark.number"));
88 * Returns the identity of the peer.
90 * @return The identity of the peer
92 public String getIdentity() {
93 return getField("identity");
97 * Returns the name of the peer. If the peer is not a darknet peer it will
100 * @return The name of the peer, or <code>null</code> if the peer is an
103 public String getMyName() {
104 return getField("myName");
108 * Returns the location of the peer.
110 * @return The location of the peer
111 * @throws NumberFormatException
112 * if the field can not be parsed
114 public double getLocation() throws NumberFormatException {
115 return Double.valueOf(getField("location"));
119 * Returns whether the peer is a testnet node.
121 * @return <code>true</code> if the peer is a testnet node,
122 * <code>false</code> otherwise
124 public boolean isTestnet() {
125 return Boolean.valueOf("testnet");
129 * Returns the version of the peer.
131 * @return The version of the peer
133 public Version getVersion() {
134 return new Version(getField("version"));
138 * Returns the negotiation types the peer supports.
140 * @return The supported negotiation types
142 public int[] getNegotiationTypes() {
143 return FcpUtils.parseMultiIntegerField(getField("auth.negTypes"));
147 * Container for the “lastGoodVersion” field.
149 * @author <a href="mailto:dr@ina-germany.de">David Roden</a>
152 public static class Version {
154 /** The name of the node implementation. */
155 private final String nodeName;
157 /** The tree version of the node. */
158 private final String treeVersion;
160 /** The protocol version of the node. */
161 private final String protocolVersion;
163 /** The build number of the node. */
164 private final int buildNumber;
167 * Creates a new Version from the given string. The string consists of
168 * the four required fields node name, tree version, protocol version,
169 * and build number, separated by a comma.
173 * @throws NullPointerException
174 * if <code>version</code> is <code>null</code>
175 * @throws IllegalArgumentException
176 * if <code>version</code> is not in the right format
178 public Version(String version) {
179 if (version == null) {
180 throw new NullPointerException("version must not be null");
182 StringTokenizer versionTokens = new StringTokenizer(version, ",");
183 if (versionTokens.countTokens() != 4) {
184 throw new IllegalArgumentException("version must consist of four fields");
186 this.nodeName = versionTokens.nextToken();
187 this.treeVersion = versionTokens.nextToken();
188 this.protocolVersion = versionTokens.nextToken();
190 this.buildNumber = Integer.valueOf(versionTokens.nextToken());
191 } catch (NumberFormatException nfe1) {
192 throw new IllegalArgumentException("last part of version must be numeric", nfe1);
197 * Creates a new Version from the given parts.
200 * The name of the node implementation
203 * @param protocolVersion
204 * The protocol version
206 * The build number of the node
208 public Version(String nodeName, String treeVersion, String protocolVersion, int buildNumber) {
209 this.nodeName = nodeName;
210 this.treeVersion = treeVersion;
211 this.protocolVersion = protocolVersion;
212 this.buildNumber = buildNumber;
216 * Returns the name of the node implementation.
218 * @return The node name
220 public String getNodeName() {
225 * The tree version of the node.
227 * @return The tree version of the node
229 public String getTreeVersion() {
234 * The protocol version of the node
236 * @return The protocol version of the node
238 public String getProtocolVersion() {
239 return protocolVersion;
243 * The build number of the node.
245 * @return The build number of the node
247 public int getBuildNumber() {
254 * Container for ARKs (address resolution keys).
256 * @author <a href="mailto:dr@ina-germany.de">David Roden</a>
259 public static class ARK {
261 /** The public URI of the ARK. */
262 private final String publicURI;
264 /** The number of the ARK. */
265 private final int number;
268 * Creates a new ARK with the given URI and number.
271 * The public URI of the ARK
273 * The number of the ARK
275 public ARK(String publicURI, String number) {
276 if ((publicURI == null) || (number == null)) {
277 throw new NullPointerException(((publicURI == null) ? "publicURI" : "number") + " must not be null");
279 this.publicURI = publicURI;
281 this.number = Integer.valueOf(number);
282 } catch (NumberFormatException nfe1) {
283 throw new IllegalArgumentException("number must be numeric", nfe1);
288 * Returns the public URI of the ARK.
290 * @return The public URI of the ARK
292 public String getPublicURI() {
297 * Returns the number of the ARK.
299 * @return The number of the ARK
301 public int getNumber() {
308 * Container for the DSA group of a peer. A DSA group consists of a base
309 * (called “g”), a prime (called “p”) and a subprime (called “q”).
312 * @author <a href="mailto:dr@ina-germany.de">David Roden</a>
315 public static class DSAGroup {
317 /** The base of the DSA group. */
318 private final String base;
320 /** The prime of the DSA group. */
321 private final String prime;
323 /** The subprime of the DSA group. */
324 private final String subprime;
327 * Creates a new DSA group with the given base (“g”), prime (“p”), and
331 * The base of the DSA group
333 * The prime of the DSA group
335 * The subprime of the DSA group
337 public DSAGroup(String base, String prime, String subprime) {
340 this.subprime = subprime;
344 * Returns the base (“g”) of the DSA group.
346 * @return The base of the DSA group
348 public String getBase() {
353 * Returns the prime (“p”) of the DSA group.
355 * @return The prime of the DSA group
357 public String getPrime() {
362 * Returns the subprime (“q”) of the DSA group.
364 * @return The subprime of the DSA group
366 public String getSubprime() {