commit df6bdc8d9bdd0ee0bf66b6d5587751bc3f86aa46
Author: iwakeh <iwakeh(a)torproject.org>
Date: Fri May 26 08:52:00 2017 +0000
Implements task-19607.
Use enums for keywords as well as enum sets and maps.
Use constants for repeated strings.
---
CHANGELOG.md | 5 +
.../impl/BridgeExtraInfoDescriptorImpl.java | 2 +-
.../descriptor/impl/BridgeNetworkStatusImpl.java | 10 +-
.../descriptor/impl/BridgePoolAssignmentImpl.java | 20 +-
.../impl/BridgeServerDescriptorImpl.java | 2 +-
.../torproject/descriptor/impl/DescriptorImpl.java | 185 +++++++++--------
.../descriptor/impl/DirSourceEntryImpl.java | 82 ++++----
.../impl/DirectoryKeyCertificateImpl.java | 95 +++++----
.../descriptor/impl/DirectorySignatureImpl.java | 23 ++-
.../descriptor/impl/ExtraInfoDescriptorImpl.java | 218 +++++++++++----------
.../java/org/torproject/descriptor/impl/Key.java | 177 +++++++++++++++++
.../descriptor/impl/MicrodescriptorImpl.java | 56 +++---
.../descriptor/impl/NetworkStatusEntryImpl.java | 70 ++++---
.../descriptor/impl/NetworkStatusImpl.java | 29 +--
.../descriptor/impl/RelayDirectoryImpl.java | 137 ++++++-------
.../impl/RelayExtraInfoDescriptorImpl.java | 2 +-
.../impl/RelayNetworkStatusConsensusImpl.java | 90 ++++-----
.../descriptor/impl/RelayNetworkStatusImpl.java | 102 +++++-----
.../impl/RelayNetworkStatusVoteImpl.java | 168 ++++++++--------
.../descriptor/impl/RelayServerDescriptorImpl.java | 2 +-
.../descriptor/impl/ServerDescriptorImpl.java | 192 +++++++++---------
21 files changed, 930 insertions(+), 737 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c76bbc1..0e39147 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,11 @@
descriptor lines, as permitted by dir-spec.txt.
- Streamline digest method names.
+ * Minor changes
+ - Turn keyword strings into enums and use the appropriate enum sets
+ and maps to avoid repeating string literals and to use more speedy
+ collection types.
+
# Changes in version 1.6.0 - 2017-02-17
diff --git a/src/main/java/org/torproject/descriptor/impl/BridgeExtraInfoDescriptorImpl.java b/src/main/java/org/torproject/descriptor/impl/BridgeExtraInfoDescriptorImpl.java
index 080dde1..0518392 100644
--- a/src/main/java/org/torproject/descriptor/impl/BridgeExtraInfoDescriptorImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/BridgeExtraInfoDescriptorImpl.java
@@ -19,7 +19,7 @@ public class BridgeExtraInfoDescriptorImpl
List<ExtraInfoDescriptor> parsedDescriptors = new ArrayList<>();
List<byte[]> splitDescriptorsBytes =
DescriptorImpl.splitRawDescriptorBytes(descriptorsBytes,
- "extra-info ");
+ Key.EXTRA_INFO.keyword + SP);
for (byte[] descriptorBytes : splitDescriptorsBytes) {
ExtraInfoDescriptor parsedDescriptor =
new BridgeExtraInfoDescriptorImpl(descriptorBytes,
diff --git a/src/main/java/org/torproject/descriptor/impl/BridgeNetworkStatusImpl.java b/src/main/java/org/torproject/descriptor/impl/BridgeNetworkStatusImpl.java
index 80aba01..88411e6 100644
--- a/src/main/java/org/torproject/descriptor/impl/BridgeNetworkStatusImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/BridgeNetworkStatusImpl.java
@@ -71,16 +71,16 @@ public class BridgeNetworkStatusImpl extends NetworkStatusImpl
this.enoughMtbfInfo = -1;
this.ignoringAdvertisedBws = -1;
- Scanner scanner = new Scanner(new String(headerBytes)).useDelimiter("\n");
+ Scanner scanner = new Scanner(new String(headerBytes)).useDelimiter(NL);
while (scanner.hasNext()) {
String line = scanner.next();
String[] parts = line.split("[ \t]+");
- String keyword = parts[0];
- switch (keyword) {
- case "published":
+ Key key = Key.get(parts[0]);
+ switch (key) {
+ case PUBLISHED:
this.parsePublishedLine(line, parts);
break;
- case "flag-thresholds":
+ case FLAG_THRESHOLDS:
this.parseFlagThresholdsLine(line, parts);
break;
default:
diff --git a/src/main/java/org/torproject/descriptor/impl/BridgePoolAssignmentImpl.java b/src/main/java/org/torproject/descriptor/impl/BridgePoolAssignmentImpl.java
index e2579e5..609797e 100644
--- a/src/main/java/org/torproject/descriptor/impl/BridgePoolAssignmentImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/BridgePoolAssignmentImpl.java
@@ -7,11 +7,9 @@ import org.torproject.descriptor.BridgePoolAssignment;
import org.torproject.descriptor.DescriptorParseException;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
+import java.util.EnumSet;
import java.util.List;
import java.util.Scanner;
-import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
@@ -24,7 +22,7 @@ public class BridgePoolAssignmentImpl extends DescriptorImpl
List<BridgePoolAssignment> parsedDescriptors = new ArrayList<>();
List<byte[]> splitDescriptorsBytes =
DescriptorImpl.splitRawDescriptorBytes(descriptorsBytes,
- "bridge-pool-assignment ");
+ Key.BRIDGE_POOL_ASSIGNMENT.keyword + SP);
for (byte[] descriptorBytes : splitDescriptorsBytes) {
BridgePoolAssignment parsedDescriptor =
new BridgePoolAssignmentImpl(descriptorBytes,
@@ -39,20 +37,18 @@ public class BridgePoolAssignmentImpl extends DescriptorImpl
throws DescriptorParseException {
super(descriptorBytes, failUnrecognizedDescriptorLines, false);
this.parseDescriptorBytes();
- Set<String> exactlyOnceKeywords = new HashSet<>(Arrays.asList(
- new String[] { "bridge-pool-assignment" }));
- this.checkExactlyOnceKeywords(exactlyOnceKeywords);
- this.checkFirstKeyword("bridge-pool-assignment");
- this.clearParsedKeywords();
+ this.checkExactlyOnceKeys(EnumSet.of(Key.BRIDGE_POOL_ASSIGNMENT));
+ this.checkFirstKey(Key.BRIDGE_POOL_ASSIGNMENT);
+ this.clearParsedKeys();
return;
}
private void parseDescriptorBytes() throws DescriptorParseException {
Scanner scanner = new Scanner(new String(this.rawDescriptorBytes))
- .useDelimiter("\n");
+ .useDelimiter(NL);
while (scanner.hasNext()) {
String line = scanner.next();
- if (line.startsWith("bridge-pool-assignment ")) {
+ if (line.startsWith(Key.BRIDGE_POOL_ASSIGNMENT.keyword + SP)) {
this.parseBridgePoolAssignmentLine(line);
} else {
this.parseBridgeLine(line);
@@ -80,7 +76,7 @@ public class BridgePoolAssignmentImpl extends DescriptorImpl
}
String fingerprint = ParseHelper.parseTwentyByteHexString(line,
parts[0]);
- String poolAndDetails = line.substring(line.indexOf(" ") + 1);
+ String poolAndDetails = line.substring(line.indexOf(SP) + 1);
this.entries.put(fingerprint, poolAndDetails);
}
diff --git a/src/main/java/org/torproject/descriptor/impl/BridgeServerDescriptorImpl.java b/src/main/java/org/torproject/descriptor/impl/BridgeServerDescriptorImpl.java
index 43548fc..900f6cd 100644
--- a/src/main/java/org/torproject/descriptor/impl/BridgeServerDescriptorImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/BridgeServerDescriptorImpl.java
@@ -19,7 +19,7 @@ public class BridgeServerDescriptorImpl extends ServerDescriptorImpl
List<ServerDescriptor> parsedDescriptors = new ArrayList<>();
List<byte[]> splitDescriptorsBytes =
DescriptorImpl.splitRawDescriptorBytes(descriptorsBytes,
- "router ");
+ Key.ROUTER.keyword + SP);
for (byte[] descriptorBytes : splitDescriptorsBytes) {
ServerDescriptor parsedDescriptor =
new BridgeServerDescriptorImpl(descriptorBytes,
diff --git a/src/main/java/org/torproject/descriptor/impl/DescriptorImpl.java b/src/main/java/org/torproject/descriptor/impl/DescriptorImpl.java
index 49f4a2e..f963fef 100644
--- a/src/main/java/org/torproject/descriptor/impl/DescriptorImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/DescriptorImpl.java
@@ -8,7 +8,7 @@ import org.torproject.descriptor.DescriptorParseException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
@@ -16,6 +16,10 @@ import java.util.Set;
public abstract class DescriptorImpl implements Descriptor {
+ public static final String NL = "\n";
+
+ public static final String SP = " ";
+
protected static List<Descriptor> parseDescriptors(
byte[] rawDescriptorBytes, String fileName,
boolean failUnrecognizedDescriptorLines)
@@ -30,33 +34,38 @@ public abstract class DescriptorImpl implements Descriptor {
first100Chars.length);
String firstLines = new String(first100Chars);
if (firstLines.startsWith("@type network-status-consensus-3 1.")
- || firstLines.startsWith("@type network-status-microdesc-"
- + "consensus-3 1.")
- || ((firstLines.startsWith("network-status-version 3")
- || firstLines.contains("\nnetwork-status-version 3"))
- && firstLines.contains("\nvote-status consensus\n"))) {
+ || firstLines.startsWith(
+ "@type network-status-microdesc-consensus-3 1.")
+ || ((firstLines.startsWith(
+ Key.NETWORK_STATUS_VERSION.keyword + SP + "3")
+ || firstLines.contains(
+ NL + Key.NETWORK_STATUS_VERSION.keyword + SP + "3"))
+ && firstLines.contains(
+ NL + Key.VOTE_STATUS.keyword + SP + "consensus" + NL))) {
parsedDescriptors.addAll(RelayNetworkStatusConsensusImpl
.parseConsensuses(rawDescriptorBytes,
failUnrecognizedDescriptorLines));
} else if (firstLines.startsWith("@type network-status-vote-3 1.")
- || ((firstLines.startsWith("network-status-version 3\n")
- || firstLines.contains("\nnetwork-status-version 3\n"))
- && firstLines.contains("\nvote-status vote\n"))) {
+ || ((firstLines.startsWith(
+ Key.NETWORK_STATUS_VERSION.keyword + SP + "3" + NL)
+ || firstLines.contains(
+ NL + Key.NETWORK_STATUS_VERSION.keyword + SP + "3" + NL))
+ && firstLines.contains(
+ NL + Key.VOTE_STATUS.keyword + SP + "vote" + NL))) {
parsedDescriptors.addAll(RelayNetworkStatusVoteImpl
.parseVotes(rawDescriptorBytes,
failUnrecognizedDescriptorLines));
} else if (firstLines.startsWith("@type bridge-network-status 1.")
- || firstLines.startsWith("r ")) {
+ || firstLines.startsWith(Key.R.keyword + SP)) {
parsedDescriptors.add(new BridgeNetworkStatusImpl(
rawDescriptorBytes, fileName, failUnrecognizedDescriptorLines));
- } else if (firstLines.startsWith(
- "@type bridge-server-descriptor 1.")) {
+ } else if (firstLines.startsWith("@type bridge-server-descriptor 1.")) {
parsedDescriptors.addAll(BridgeServerDescriptorImpl
.parseDescriptors(rawDescriptorBytes,
failUnrecognizedDescriptorLines));
} else if (firstLines.startsWith("@type server-descriptor 1.")
- || firstLines.startsWith("router ")
- || firstLines.contains("\nrouter ")) {
+ || firstLines.startsWith(Key.ROUTER.keyword + SP)
+ || firstLines.contains(NL + Key.ROUTER.keyword + SP)) {
parsedDescriptors.addAll(RelayServerDescriptorImpl
.parseDescriptors(rawDescriptorBytes,
failUnrecognizedDescriptorLines));
@@ -65,42 +74,45 @@ public abstract class DescriptorImpl implements Descriptor {
.parseDescriptors(rawDescriptorBytes,
failUnrecognizedDescriptorLines));
} else if (firstLines.startsWith("@type extra-info 1.")
- || firstLines.startsWith("extra-info ")
- || firstLines.contains("\nextra-info ")) {
+ || firstLines.startsWith(Key.EXTRA_INFO.keyword + SP)
+ || firstLines.contains(NL + Key.EXTRA_INFO.keyword + SP)) {
parsedDescriptors.addAll(RelayExtraInfoDescriptorImpl
.parseDescriptors(rawDescriptorBytes,
failUnrecognizedDescriptorLines));
} else if (firstLines.startsWith("@type microdescriptor 1.")
- || firstLines.startsWith("onion-key\n")
- || firstLines.contains("\nonion-key\n")) {
+ || firstLines.startsWith(Key.ONION_KEY.keyword + NL)
+ || firstLines.contains(NL + Key.ONION_KEY.keyword + NL)) {
parsedDescriptors.addAll(MicrodescriptorImpl
.parseDescriptors(rawDescriptorBytes,
failUnrecognizedDescriptorLines));
} else if (firstLines.startsWith("@type bridge-pool-assignment 1.")
- || firstLines.startsWith("bridge-pool-assignment ")
- || firstLines.contains("\nbridge-pool-assignment ")) {
+ || firstLines.startsWith(Key.BRIDGE_POOL_ASSIGNMENT.keyword + SP)
+ || firstLines.contains(NL + Key.BRIDGE_POOL_ASSIGNMENT.keyword + SP)) {
parsedDescriptors.addAll(BridgePoolAssignmentImpl
.parseDescriptors(rawDescriptorBytes,
failUnrecognizedDescriptorLines));
} else if (firstLines.startsWith("@type dir-key-certificate-3 1.")
- || firstLines.startsWith("dir-key-certificate-version ")
- || firstLines.contains("\ndir-key-certificate-version ")) {
+ || firstLines.startsWith(Key.DIR_KEY_CERTIFICATE_VERSION.keyword + SP)
+ || firstLines.contains(
+ NL + Key.DIR_KEY_CERTIFICATE_VERSION.keyword + SP)) {
parsedDescriptors.addAll(DirectoryKeyCertificateImpl
.parseDescriptors(rawDescriptorBytes,
failUnrecognizedDescriptorLines));
} else if (firstLines.startsWith("@type tordnsel 1.")
- || firstLines.startsWith("ExitNode ")
- || firstLines.contains("\nExitNode ")) {
+ || firstLines.startsWith("ExitNode" + SP)
+ || firstLines.contains(NL + "ExitNode" + SP)) {
parsedDescriptors.add(new ExitListImpl(rawDescriptorBytes, fileName,
failUnrecognizedDescriptorLines));
} else if (firstLines.startsWith("@type network-status-2 1.")
- || firstLines.startsWith("network-status-version 2\n")
- || firstLines.contains("\nnetwork-status-version 2\n")) {
+ || firstLines.startsWith(
+ Key.NETWORK_STATUS_VERSION.keyword + SP + "2" + NL)
+ || firstLines.contains(
+ NL + Key.NETWORK_STATUS_VERSION.keyword + SP + "2" + NL)) {
parsedDescriptors.add(new RelayNetworkStatusImpl(rawDescriptorBytes,
failUnrecognizedDescriptorLines));
} else if (firstLines.startsWith("@type directory 1.")
- || firstLines.startsWith("signed-directory\n")
- || firstLines.contains("\nsigned-directory\n")) {
+ || firstLines.startsWith(Key.SIGNED_DIRECTORY.keyword + NL)
+ || firstLines.contains(NL + Key.SIGNED_DIRECTORY.keyword + NL)) {
parsedDescriptors.add(new RelayDirectoryImpl(rawDescriptorBytes,
failUnrecognizedDescriptorLines));
} else if (firstLines.startsWith("@type torperf 1.")) {
@@ -116,7 +128,7 @@ public abstract class DescriptorImpl implements Descriptor {
protected static List<byte[]> splitRawDescriptorBytes(
byte[] rawDescriptorBytes, String startToken) {
List<byte[]> rawDescriptors = new ArrayList<>();
- String splitToken = "\n" + startToken;
+ String splitToken = NL + startToken;
String ascii;
try {
ascii = new String(rawDescriptorBytes, "US-ASCII");
@@ -126,7 +138,7 @@ public abstract class DescriptorImpl implements Descriptor {
int endAllDescriptors = rawDescriptorBytes.length;
int startAnnotations = 0;
boolean containsAnnotations = ascii.startsWith("@")
- || ascii.contains("\n@");
+ || ascii.contains(NL + "@");
while (startAnnotations < endAllDescriptors) {
int startDescriptor;
if (ascii.indexOf(startToken, startAnnotations) == 0) {
@@ -141,7 +153,7 @@ public abstract class DescriptorImpl implements Descriptor {
}
int endDescriptor = -1;
if (containsAnnotations) {
- endDescriptor = ascii.indexOf("\n@", startDescriptor);
+ endDescriptor = ascii.indexOf(NL + "@", startDescriptor);
}
if (endDescriptor < 0) {
endDescriptor = ascii.indexOf(splitToken, startDescriptor);
@@ -183,7 +195,7 @@ public abstract class DescriptorImpl implements Descriptor {
this.failUnrecognizedDescriptorLines =
failUnrecognizedDescriptorLines;
this.cutOffAnnotations(rawDescriptorBytes);
- this.countKeywords(rawDescriptorBytes, blankLinesAllowed);
+ this.countKeys(rawDescriptorBytes, blankLinesAllowed);
}
/* Parse annotation lines from the descriptor bytes. */
@@ -194,8 +206,8 @@ public abstract class DescriptorImpl implements Descriptor {
String ascii = new String(rawDescriptorBytes);
int start = 0;
while ((start == 0 && ascii.startsWith("@"))
- || (start > 0 && ascii.indexOf("\n@", start - 1) >= 0)) {
- int end = ascii.indexOf("\n", start);
+ || (start > 0 && ascii.indexOf(NL + "@", start - 1) >= 0)) {
+ int end = ascii.indexOf(NL, start);
if (end < 0) {
throw new DescriptorParseException("Annotation line does not "
+ "contain a newline.");
@@ -217,130 +229,129 @@ public abstract class DescriptorImpl implements Descriptor {
return new ArrayList<>(this.annotations);
}
- private String firstKeyword;
+ private Key firstKey = Key.EMPTY;
- private String lastKeyword;
+ private Key lastKey = Key.EMPTY;
- private Map<String, Integer> parsedKeywords = new HashMap<>();
+ private Map<Key, Integer> parsedKeys = new EnumMap<>(Key.class);
/* Count parsed keywords for consistency checks by subclasses. */
- private void countKeywords(byte[] rawDescriptorBytes,
+ private void countKeys(byte[] rawDescriptorBytes,
boolean blankLinesAllowed) throws DescriptorParseException {
if (rawDescriptorBytes.length == 0) {
throw new DescriptorParseException("Descriptor is empty.");
}
String descriptorString = new String(rawDescriptorBytes);
- if (!blankLinesAllowed && (descriptorString.startsWith("\n")
- || descriptorString.contains("\n\n"))) {
+ if (!blankLinesAllowed && (descriptorString.startsWith(NL)
+ || descriptorString.contains(NL + NL))) {
throw new DescriptorParseException("Blank lines are not allowed.");
}
boolean skipCrypto = false;
- Scanner scanner = new Scanner(descriptorString).useDelimiter("\n");
+ Scanner scanner = new Scanner(descriptorString).useDelimiter(NL);
while (scanner.hasNext()) {
String line = scanner.next();
- if (line.startsWith("-----BEGIN")) {
+ if (line.startsWith(Key.CRYPTO_BEGIN.keyword)) {
skipCrypto = true;
- } else if (line.startsWith("-----END")) {
+ } else if (line.startsWith(Key.CRYPTO_END.keyword)) {
skipCrypto = false;
} else if (!line.isEmpty() && !line.startsWith("@")
&& !skipCrypto) {
- String lineNoOpt = line.startsWith("opt ")
- ? line.substring("opt ".length()) : line;
- String keyword = lineNoOpt.split(" ", -1)[0];
+ String lineNoOpt = line.startsWith(Key.OPT.keyword + SP)
+ ? line.substring(Key.OPT.keyword.length() + 1) : line;
+ String keyword = lineNoOpt.split(SP, -1)[0];
if (keyword.equals("")) {
throw new DescriptorParseException("Illegal keyword in line '"
+ line + "'.");
}
- if (this.firstKeyword == null) {
- this.firstKeyword = keyword;
+ Key key = Key.get(keyword);
+ if (Key.EMPTY == this.firstKey) {
+ this.firstKey = key;
}
- lastKeyword = keyword;
- if (parsedKeywords.containsKey(keyword)) {
- parsedKeywords.put(keyword, parsedKeywords.get(keyword) + 1);
+ lastKey = key;
+ if (parsedKeys.containsKey(key)) {
+ parsedKeys.put(key, parsedKeys.get(key) + 1);
} else {
- parsedKeywords.put(keyword, 1);
+ parsedKeys.put(key, 1);
}
}
}
}
- protected void checkFirstKeyword(String keyword)
+ protected void checkFirstKey(Key key)
throws DescriptorParseException {
- if (this.firstKeyword == null
- || !this.firstKeyword.equals(keyword)) {
- throw new DescriptorParseException("Keyword '" + keyword + "' must "
+ if (this.firstKey != key) {
+ throw new DescriptorParseException("Keyword '" + key.keyword + "' must "
+ "be contained in the first line.");
}
}
- protected void checkLastKeyword(String keyword)
+ protected void checkLastKey(Key key)
throws DescriptorParseException {
- if (this.lastKeyword == null
- || !this.lastKeyword.equals(keyword)) {
- throw new DescriptorParseException("Keyword '" + keyword + "' must "
+ if (this.lastKey != key) {
+ throw new DescriptorParseException("Keyword '" + key.keyword + "' must "
+ "be contained in the last line.");
}
}
- protected void checkExactlyOnceKeywords(Set<String> keywords)
+ protected void checkExactlyOnceKeys(Set<Key> keys)
throws DescriptorParseException {
- for (String keyword : keywords) {
+ for (Key key : keys) {
int contained = 0;
- if (this.parsedKeywords.containsKey(keyword)) {
- contained = this.parsedKeywords.get(keyword);
+ if (this.parsedKeys.containsKey(key)) {
+ contained = this.parsedKeys.get(key);
}
if (contained != 1) {
- throw new DescriptorParseException("Keyword '" + keyword + "' is "
+ throw new DescriptorParseException("Keyword '" + key.keyword + "' is "
+ "contained " + contained + " times, but must be contained "
+ "exactly once.");
}
}
}
- protected void checkAtLeastOnceKeywords(Set<String> keywords)
+ protected void checkAtLeastOnceKeys(Set<Key> keys)
throws DescriptorParseException {
- for (String keyword : keywords) {
- if (!this.parsedKeywords.containsKey(keyword)) {
- throw new DescriptorParseException("Keyword '" + keyword + "' is "
+ for (Key key : keys) {
+ if (!this.parsedKeys.containsKey(key)) {
+ throw new DescriptorParseException("Keyword '" + key.keyword + "' is "
+ "contained 0 times, but must be contained at least once.");
}
}
}
- protected void checkAtMostOnceKeywords(Set<String> keywords)
+ protected void checkAtMostOnceKeys(Set<Key> keys)
throws DescriptorParseException {
- for (String keyword : keywords) {
- if (this.parsedKeywords.containsKey(keyword)
- && this.parsedKeywords.get(keyword) > 1) {
- throw new DescriptorParseException("Keyword '" + keyword + "' is "
- + "contained " + this.parsedKeywords.get(keyword) + " times, "
+ for (Key key : keys) {
+ if (this.parsedKeys.containsKey(key)
+ && this.parsedKeys.get(key) > 1) {
+ throw new DescriptorParseException("Keyword '" + key.keyword + "' is "
+ + "contained " + this.parsedKeys.get(key) + " times, "
+ "but must be contained at most once.");
}
}
}
- protected void checkKeywordsDependOn(Set<String> dependentKeywords,
- String dependingKeyword) throws DescriptorParseException {
- for (String dependentKeyword : dependentKeywords) {
- if (this.parsedKeywords.containsKey(dependentKeyword)
- && !this.parsedKeywords.containsKey(dependingKeyword)) {
- throw new DescriptorParseException("Keyword '" + dependentKeyword
- + "' is contained, but keyword '" + dependingKeyword + "' is "
+ protected void checkKeysDependOn(Set<Key> dependentKeys,
+ Key dependingKey) throws DescriptorParseException {
+ for (Key dependentKey : dependentKeys) {
+ if (this.parsedKeys.containsKey(dependentKey)
+ && !this.parsedKeys.containsKey(dependingKey)) {
+ throw new DescriptorParseException("Keyword '" + dependentKey.keyword
+ + "' is contained, but keyword '" + dependingKey.keyword + "' is "
+ "not.");
}
}
}
- protected int getKeywordCount(String keyword) {
- if (!this.parsedKeywords.containsKey(keyword)) {
+ protected int getKeyCount(Key key) {
+ if (!this.parsedKeys.containsKey(key)) {
return 0;
} else {
- return this.parsedKeywords.get(keyword);
+ return this.parsedKeys.get(key);
}
}
- protected void clearParsedKeywords() {
- this.parsedKeywords = null;
+ protected void clearParsedKeys() {
+ this.parsedKeys = null;
}
}
diff --git a/src/main/java/org/torproject/descriptor/impl/DirSourceEntryImpl.java b/src/main/java/org/torproject/descriptor/impl/DirSourceEntryImpl.java
index 539d211..fd2c783 100644
--- a/src/main/java/org/torproject/descriptor/impl/DirSourceEntryImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/DirSourceEntryImpl.java
@@ -3,14 +3,17 @@
package org.torproject.descriptor.impl;
+import static org.torproject.descriptor.impl.DescriptorImpl.NL;
+import static org.torproject.descriptor.impl.DescriptorImpl.SP;
+
import org.torproject.descriptor.DescriptorParseException;
import org.torproject.descriptor.DirSourceEntry;
import java.util.ArrayList;
+import java.util.EnumSet;
import java.util.List;
import java.util.Scanner;
-import java.util.SortedSet;
-import java.util.TreeSet;
+import java.util.Set;
public class DirSourceEntryImpl implements DirSourceEntry {
@@ -37,72 +40,67 @@ public class DirSourceEntryImpl implements DirSourceEntry {
this.dirSourceEntryBytes = dirSourceEntryBytes;
this.failUnrecognizedDescriptorLines =
failUnrecognizedDescriptorLines;
- this.initializeKeywords();
this.parseDirSourceEntryBytes();
- this.checkAndClearKeywords();
+ this.checkAndClearKeys();
}
- private SortedSet<String> exactlyOnceKeywords;
-
- private SortedSet<String> atMostOnceKeywords;
+ private Set<Key> exactlyOnceKeys = EnumSet.of(
+ Key.DIR_SOURCE, Key.VOTE_DIGEST);
- private void initializeKeywords() {
- this.exactlyOnceKeywords = new TreeSet<>();
- this.exactlyOnceKeywords.add("dir-source");
- this.exactlyOnceKeywords.add("vote-digest");
- this.atMostOnceKeywords = new TreeSet<>();
- this.atMostOnceKeywords.add("contact");
- }
+ private Set<Key> atMostOnceKeys = EnumSet.of(Key.CONTACT);
- private void parsedExactlyOnceKeyword(String keyword)
+ private void parsedExactlyOnceKey(Key key)
throws DescriptorParseException {
- if (!this.exactlyOnceKeywords.contains(keyword)) {
- throw new DescriptorParseException("Duplicate '" + keyword
+ if (!this.exactlyOnceKeys.contains(key)) {
+ throw new DescriptorParseException("Duplicate '" + key.keyword
+ "' line in dir-source.");
}
- this.exactlyOnceKeywords.remove(keyword);
+ this.exactlyOnceKeys.remove(key);
}
- private void parsedAtMostOnceKeyword(String keyword)
+ private void parsedAtMostOnceKey(Key key)
throws DescriptorParseException {
- if (!this.atMostOnceKeywords.contains(keyword)) {
- throw new DescriptorParseException("Duplicate " + keyword + "line "
+ if (!this.atMostOnceKeys.contains(key)) {
+ throw new DescriptorParseException("Duplicate " + key.keyword + "line "
+ "in dir-source.");
}
- this.atMostOnceKeywords.remove(keyword);
+ this.atMostOnceKeys.remove(key);
}
- private void checkAndClearKeywords() throws DescriptorParseException {
- if (!this.exactlyOnceKeywords.isEmpty()) {
- throw new DescriptorParseException("dir-source does not contain a '"
- + this.exactlyOnceKeywords.first() + "' line.");
+ private void checkAndClearKeys() throws DescriptorParseException {
+ if (!this.exactlyOnceKeys.isEmpty()) {
+ for (Key key : this.exactlyOnceKeys) {
+ throw new DescriptorParseException("dir-source does not contain a '"
+ + key.keyword + "' line.");
+ }
}
- this.exactlyOnceKeywords = null;
- this.atMostOnceKeywords = null;
+ this.exactlyOnceKeys = null;
+ this.atMostOnceKeys = null;
}
private void parseDirSourceEntryBytes()
throws DescriptorParseException {
Scanner scanner = new Scanner(new String(this.dirSourceEntryBytes))
- .useDelimiter("\n");
+ .useDelimiter(NL);
boolean skipCrypto = false;
while (scanner.hasNext()) {
String line = scanner.next();
- String[] parts = line.split(" ");
- switch (parts[0]) {
- case "dir-source":
+ String[] parts = line.split(SP);
+ Key key = Key.get(parts[0]);
+ switch (key) {
+ case DIR_SOURCE:
this.parseDirSourceLine(line);
break;
- case "contact":
+ case CONTACT:
this.parseContactLine(line);
break;
- case "vote-digest":
+ case VOTE_DIGEST:
this.parseVoteDigestLine(line);
break;
- case "-----BEGIN":
+ case CRYPTO_BEGIN:
skipCrypto = true;
break;
- case "-----END":
+ case CRYPTO_END:
skipCrypto = false;
break;
default:
@@ -123,7 +121,7 @@ public class DirSourceEntryImpl implements DirSourceEntry {
private void parseDirSourceLine(String line)
throws DescriptorParseException {
- this.parsedExactlyOnceKeyword("dir-source");
+ this.parsedExactlyOnceKey(Key.DIR_SOURCE);
String[] parts = line.split("[ \t]+");
if (parts.length != 7) {
throw new DescriptorParseException("Invalid line '" + line + "'.");
@@ -133,7 +131,7 @@ public class DirSourceEntryImpl implements DirSourceEntry {
nickname = nickname.substring(0, nickname.length()
- "-legacy".length());
this.isLegacy = true;
- this.parsedExactlyOnceKeyword("vote-digest");
+ this.parsedExactlyOnceKey(Key.VOTE_DIGEST);
}
this.nickname = ParseHelper.parseNickname(line, nickname);
this.identity = ParseHelper.parseTwentyByteHexString(line, parts[2]);
@@ -149,9 +147,9 @@ public class DirSourceEntryImpl implements DirSourceEntry {
private void parseContactLine(String line)
throws DescriptorParseException {
- this.parsedAtMostOnceKeyword("contact");
- if (line.length() > "contact ".length()) {
- this.contactLine = line.substring("contact ".length());
+ this.parsedAtMostOnceKey(Key.CONTACT);
+ if (line.length() > Key.CONTACT.keyword.length() + 1) {
+ this.contactLine = line.substring(Key.CONTACT.keyword.length() + 1);
} else {
this.contactLine = "";
}
@@ -159,7 +157,7 @@ public class DirSourceEntryImpl implements DirSourceEntry {
private void parseVoteDigestLine(String line)
throws DescriptorParseException {
- this.parsedExactlyOnceKeyword("vote-digest");
+ this.parsedExactlyOnceKey(Key.VOTE_DIGEST);
String[] parts = line.split("[ \t]+");
if (parts.length != 2) {
throw new DescriptorParseException("Invalid line '" + line + "'.");
diff --git a/src/main/java/org/torproject/descriptor/impl/DirectoryKeyCertificateImpl.java b/src/main/java/org/torproject/descriptor/impl/DirectoryKeyCertificateImpl.java
index 64df7aa..0bb08fd 100644
--- a/src/main/java/org/torproject/descriptor/impl/DirectoryKeyCertificateImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/DirectoryKeyCertificateImpl.java
@@ -10,8 +10,7 @@ import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
+import java.util.EnumSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
@@ -27,7 +26,7 @@ public class DirectoryKeyCertificateImpl extends DescriptorImpl
List<DirectoryKeyCertificate> parsedDescriptors = new ArrayList<>();
List<byte[]> splitDescriptorsBytes =
DirectoryKeyCertificateImpl.splitRawDescriptorBytes(
- descriptorsBytes, "dir-key-certificate-version ");
+ descriptorsBytes, Key.DIR_KEY_CERTIFICATE_VERSION.keyword + SP);
for (byte[] descriptorBytes : splitDescriptorsBytes) {
DirectoryKeyCertificate parsedDescriptor =
new DirectoryKeyCertificateImpl(descriptorBytes,
@@ -43,90 +42,90 @@ public class DirectoryKeyCertificateImpl extends DescriptorImpl
super(rawDescriptorBytes, failUnrecognizedDescriptorLines, false);
this.parseDescriptorBytes();
this.calculateDigest();
- Set<String> exactlyOnceKeywords = new HashSet<>(Arrays.asList((
- "dir-key-certificate-version,fingerprint,dir-identity-key,"
- + "dir-key-published,dir-key-expires,dir-signing-key,"
- + "dir-key-certification").split(",")));
- this.checkExactlyOnceKeywords(exactlyOnceKeywords);
- Set<String> atMostOnceKeywords = new HashSet<>(Arrays.asList((
- "dir-address,dir-key-crosscert").split(",")));
- this.checkAtMostOnceKeywords(atMostOnceKeywords);
- this.checkFirstKeyword("dir-key-certificate-version");
- this.checkLastKeyword("dir-key-certification");
- this.clearParsedKeywords();
+ Set<Key> exactlyOnceKeys = EnumSet.of(
+ Key.DIR_KEY_CERTIFICATE_VERSION, Key.FINGERPRINT, Key.DIR_IDENTITY_KEY,
+ Key.DIR_KEY_PUBLISHED, Key.DIR_KEY_EXPIRES, Key.DIR_SIGNING_KEY,
+ Key.DIR_KEY_CERTIFICATION);
+ this.checkExactlyOnceKeys(exactlyOnceKeys);
+ Set<Key> atMostOnceKeys = EnumSet.of(
+ Key.DIR_ADDRESS, Key.DIR_KEY_CROSSCERT);
+ this.checkAtMostOnceKeys(atMostOnceKeys);
+ this.checkFirstKey(Key.DIR_KEY_CERTIFICATE_VERSION);
+ this.checkLastKey(Key.DIR_KEY_CERTIFICATION);
+ this.clearParsedKeys();
}
private void parseDescriptorBytes() throws DescriptorParseException {
Scanner scanner = new Scanner(new String(this.rawDescriptorBytes))
- .useDelimiter("\n");
- String nextCrypto = "";
+ .useDelimiter(NL);
+ Key nextCrypto = Key.EMPTY;
StringBuilder crypto = null;
while (scanner.hasNext()) {
String line = scanner.next();
String[] parts = line.split("[ \t]+");
- String keyword = parts[0];
- switch (keyword) {
- case "dir-key-certificate-version":
+ Key key = Key.get(parts[0]);
+ switch (key) {
+ case DIR_KEY_CERTIFICATE_VERSION:
this.parseDirKeyCertificateVersionLine(line, parts);
break;
- case "dir-address":
+ case DIR_ADDRESS:
this.parseDirAddressLine(line, parts);
break;
- case "fingerprint":
+ case FINGERPRINT:
this.parseFingerprintLine(line, parts);
break;
- case "dir-identity-key":
+ case DIR_IDENTITY_KEY:
this.parseDirIdentityKeyLine(line, parts);
- nextCrypto = "dir-identity-key";
+ nextCrypto = key;
break;
- case "dir-key-published":
+ case DIR_KEY_PUBLISHED:
this.parseDirKeyPublishedLine(line, parts);
break;
- case "dir-key-expires":
+ case DIR_KEY_EXPIRES:
this.parseDirKeyExpiresLine(line, parts);
break;
- case "dir-signing-key":
+ case DIR_SIGNING_KEY:
this.parseDirSigningKeyLine(line, parts);
- nextCrypto = "dir-signing-key";
+ nextCrypto = key;
break;
- case "dir-key-crosscert":
+ case DIR_KEY_CROSSCERT:
this.parseDirKeyCrosscertLine(line, parts);
- nextCrypto = "dir-key-crosscert";
+ nextCrypto = key;
break;
- case "dir-key-certification":
+ case DIR_KEY_CERTIFICATION:
this.parseDirKeyCertificationLine(line, parts);
- nextCrypto = "dir-key-certification";
+ nextCrypto = key;
break;
- case "-----BEGIN":
+ case CRYPTO_BEGIN:
crypto = new StringBuilder();
- crypto.append(line).append("\n");
+ crypto.append(line).append(NL);
break;
- case "-----END":
- crypto.append(line).append("\n");
+ case CRYPTO_END:
+ crypto.append(line).append(NL);
String cryptoString = crypto.toString();
crypto = null;
switch (nextCrypto) {
- case "dir-identity-key":
+ case DIR_IDENTITY_KEY:
this.dirIdentityKey = cryptoString;
break;
- case "dir-signing-key":
+ case DIR_SIGNING_KEY:
this.dirSigningKey = cryptoString;
break;
- case "dir-key-crosscert":
+ case DIR_KEY_CROSSCERT:
this.dirKeyCrosscert = cryptoString;
break;
- case "dir-key-certification":
+ case DIR_KEY_CERTIFICATION:
this.dirKeyCertification = cryptoString;
break;
default:
throw new DescriptorParseException("Unrecognized crypto "
+ "block in directory key certificate.");
}
- nextCrypto = "";
+ nextCrypto = Key.EMPTY;
break;
default:
if (crypto != null) {
- crypto.append(line).append("\n");
+ crypto.append(line).append(NL);
} else {
if (this.failUnrecognizedDescriptorLines) {
throw new DescriptorParseException("Unrecognized line '"
@@ -144,7 +143,7 @@ public class DirectoryKeyCertificateImpl extends DescriptorImpl
private void parseDirKeyCertificateVersionLine(String line,
String[] parts) throws DescriptorParseException {
- if (!line.equals("dir-key-certificate-version 3")) {
+ if (!line.equals(Key.DIR_KEY_CERTIFICATE_VERSION.keyword + SP + "3")) {
throw new DescriptorParseException("Illegal directory key "
+ "certificate version number in line '" + line + "'.");
}
@@ -174,7 +173,7 @@ public class DirectoryKeyCertificateImpl extends DescriptorImpl
private void parseDirIdentityKeyLine(String line, String[] parts)
throws DescriptorParseException {
- if (!line.equals("dir-identity-key")) {
+ if (!line.equals(Key.DIR_IDENTITY_KEY.keyword)) {
throw new DescriptorParseException("Illegal line '" + line + "'.");
}
}
@@ -193,21 +192,21 @@ public class DirectoryKeyCertificateImpl extends DescriptorImpl
private void parseDirSigningKeyLine(String line, String[] parts)
throws DescriptorParseException {
- if (!line.equals("dir-signing-key")) {
+ if (!line.equals(Key.DIR_SIGNING_KEY.keyword)) {
throw new DescriptorParseException("Illegal line '" + line + "'.");
}
}
private void parseDirKeyCrosscertLine(String line, String[] parts)
throws DescriptorParseException {
- if (!line.equals("dir-key-crosscert")) {
+ if (!line.equals(Key.DIR_KEY_CROSSCERT.keyword)) {
throw new DescriptorParseException("Illegal line '" + line + "'.");
}
}
private void parseDirKeyCertificationLine(String line, String[] parts)
throws DescriptorParseException {
- if (!line.equals("dir-key-certification")) {
+ if (!line.equals(Key.DIR_KEY_CERTIFICATION.keyword)) {
throw new DescriptorParseException("Illegal line '" + line + "'.");
}
}
@@ -215,8 +214,8 @@ public class DirectoryKeyCertificateImpl extends DescriptorImpl
private void calculateDigest() throws DescriptorParseException {
try {
String ascii = new String(this.getRawDescriptorBytes(), "US-ASCII");
- String startToken = "dir-key-certificate-version ";
- String sigToken = "\ndir-key-certification\n";
+ String startToken = Key.DIR_KEY_CERTIFICATE_VERSION.keyword + SP;
+ String sigToken = NL + Key.DIR_KEY_CERTIFICATION.keyword + NL;
int start = ascii.indexOf(startToken);
int sig = ascii.indexOf(sigToken) + sigToken.length();
if (start >= 0 && sig >= 0 && sig > start) {
diff --git a/src/main/java/org/torproject/descriptor/impl/DirectorySignatureImpl.java b/src/main/java/org/torproject/descriptor/impl/DirectorySignatureImpl.java
index 7cf427a..674b634 100644
--- a/src/main/java/org/torproject/descriptor/impl/DirectorySignatureImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/DirectorySignatureImpl.java
@@ -3,6 +3,9 @@
package org.torproject.descriptor.impl;
+import static org.torproject.descriptor.impl.DescriptorImpl.NL;
+import static org.torproject.descriptor.impl.DescriptorImpl.SP;
+
import org.torproject.descriptor.DescriptorParseException;
import org.torproject.descriptor.DirectorySignature;
@@ -36,14 +39,14 @@ public class DirectorySignatureImpl implements DirectorySignature {
private void parseDirectorySignatureBytes()
throws DescriptorParseException {
Scanner scanner = new Scanner(new String(this.directorySignatureBytes))
- .useDelimiter("\n");
+ .useDelimiter(NL);
StringBuilder crypto = null;
while (scanner.hasNext()) {
String line = scanner.next();
- String[] parts = line.split(" ", -1);
- String keyword = parts[0];
- switch (keyword) {
- case "directory-signature":
+ String[] parts = line.split(SP, -1);
+ Key key = Key.get(parts[0]);
+ switch (key) {
+ case DIRECTORY_SIGNATURE:
int algorithmOffset = 0;
switch (parts.length) {
case 4:
@@ -61,19 +64,19 @@ public class DirectorySignatureImpl implements DirectorySignature {
this.signingKeyDigest = ParseHelper.parseHexString(
line, parts[2 + algorithmOffset]);
break;
- case "-----BEGIN":
+ case CRYPTO_BEGIN:
crypto = new StringBuilder();
- crypto.append(line).append("\n");
+ crypto.append(line).append(NL);
break;
- case "-----END":
- crypto.append(line).append("\n");
+ case CRYPTO_END:
+ crypto.append(line).append(NL);
String cryptoString = crypto.toString();
crypto = null;
this.signature = cryptoString;
break;
default:
if (crypto != null) {
- crypto.append(line).append("\n");
+ crypto.append(line).append(NL);
} else {
if (this.failUnrecognizedDescriptorLines) {
throw new DescriptorParseException("Unrecognized line '"
diff --git a/src/main/java/org/torproject/descriptor/impl/ExtraInfoDescriptorImpl.java b/src/main/java/org/torproject/descriptor/impl/ExtraInfoDescriptorImpl.java
index dd1bc07..fd55925 100644
--- a/src/main/java/org/torproject/descriptor/impl/ExtraInfoDescriptorImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/ExtraInfoDescriptorImpl.java
@@ -14,8 +14,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
+import java.util.EnumSet;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
@@ -28,6 +28,16 @@ import javax.xml.bind.DatatypeConverter;
public abstract class ExtraInfoDescriptorImpl extends DescriptorImpl
implements ExtraInfoDescriptor {
+ private Set<Key> exactlyOnceKeys = EnumSet.of(
+ Key.EXTRA_INFO, Key.PUBLISHED);
+
+ private static final Set<Key> atMostOnceKeys = EnumSet.of(
+ Key.IDENTITY_ED25519, Key.MASTER_KEY_ED25519, Key.READ_HISTORY,
+ Key.WRITE_HISTORY, Key.DIRREQ_READ_HISTORY, Key.DIRREQ_WRITE_HISTORY,
+ Key.GEOIP_DB_DIGEST, Key.GEOIP6_DB_DIGEST, Key.ROUTER_SIG_ED25519,
+ Key.ROUTER_SIGNATURE, Key.ROUTER_DIGEST_SHA256, Key.ROUTER_DIGEST,
+ Key.PADDING_COUNTS);
+
protected ExtraInfoDescriptorImpl(byte[] descriptorBytes,
boolean failUnrecognizedDescriptorLines)
throws DescriptorParseException {
@@ -35,231 +45,223 @@ public abstract class ExtraInfoDescriptorImpl extends DescriptorImpl
this.parseDescriptorBytes();
this.calculateDigest();
this.calculateDigestSha256();
- Set<String> exactlyOnceKeywords = new HashSet<>(Arrays.asList((
- "extra-info,published").split(",")));
- this.checkExactlyOnceKeywords(exactlyOnceKeywords);
- Set<String> dirreqStatsKeywords = new HashSet<>(Arrays.asList((
- "dirreq-stats-end,dirreq-v2-ips,dirreq-v3-ips,dirreq-v2-reqs,"
- + "dirreq-v3-reqs,dirreq-v2-share,dirreq-v3-share,dirreq-v2-resp,"
- + "dirreq-v3-resp,dirreq-v2-direct-dl,dirreq-v3-direct-dl,"
- + "dirreq-v2-tunneled-dl,dirreq-v3-tunneled-dl,").split(",")));
- Set<String> entryStatsKeywords = new HashSet<>(Arrays.asList(
- "entry-stats-end,entry-ips".split(",")));
- Set<String> cellStatsKeywords = new HashSet<>(Arrays.asList((
- "cell-stats-end,cell-processed-cells,cell-queued-cells,"
- + "cell-time-in-queue,cell-circuits-per-decile").split(",")));
- Set<String> connBiDirectStatsKeywords = new HashSet<>(
- Arrays.asList("conn-bi-direct".split(",")));
- Set<String> exitStatsKeywords = new HashSet<>(Arrays.asList((
- "exit-stats-end,exit-kibibytes-written,exit-kibibytes-read,"
- + "exit-streams-opened").split(",")));
- Set<String> bridgeStatsKeywords = new HashSet<>(Arrays.asList(
- "bridge-stats-end,bridge-stats-ips".split(",")));
- Set<String> atMostOnceKeywords = new HashSet<>(Arrays.asList((
- "identity-ed25519,master-key-ed25519,read-history,write-history,"
- + "dirreq-read-history,dirreq-write-history,geoip-db-digest,"
- + "router-sig-ed25519,router-signature,router-digest-sha256,"
- + "router-digest").split(",")));
- atMostOnceKeywords.addAll(dirreqStatsKeywords);
- atMostOnceKeywords.addAll(entryStatsKeywords);
- atMostOnceKeywords.addAll(cellStatsKeywords);
- atMostOnceKeywords.addAll(connBiDirectStatsKeywords);
- atMostOnceKeywords.addAll(exitStatsKeywords);
- atMostOnceKeywords.addAll(bridgeStatsKeywords);
- atMostOnceKeywords.add("padding-counts");
- this.checkAtMostOnceKeywords(atMostOnceKeywords);
- this.checkKeywordsDependOn(dirreqStatsKeywords, "dirreq-stats-end");
- this.checkKeywordsDependOn(entryStatsKeywords, "entry-stats-end");
- this.checkKeywordsDependOn(cellStatsKeywords, "cell-stats-end");
- this.checkKeywordsDependOn(exitStatsKeywords, "exit-stats-end");
- this.checkKeywordsDependOn(bridgeStatsKeywords, "bridge-stats-end");
- this.checkFirstKeyword("extra-info");
- this.clearParsedKeywords();
+ this.checkExactlyOnceKeys(exactlyOnceKeys);
+ Set<Key> dirreqStatsKeys = EnumSet.of(
+ Key.DIRREQ_STATS_END, Key.DIRREQ_V2_IPS, Key.DIRREQ_V3_IPS,
+ Key.DIRREQ_V2_REQS, Key.DIRREQ_V3_REQS, Key.DIRREQ_V2_SHARE,
+ Key.DIRREQ_V3_SHARE, Key.DIRREQ_V2_RESP, Key.DIRREQ_V3_RESP,
+ Key.DIRREQ_V2_DIRECT_DL, Key.DIRREQ_V3_DIRECT_DL,
+ Key.DIRREQ_V2_TUNNELED_DL, Key.DIRREQ_V3_TUNNELED_DL);
+ Set<Key> entryStatsKeys = EnumSet.of(
+ Key.ENTRY_STATS_END, Key.ENTRY_IPS);
+ Set<Key> cellStatsKeys = EnumSet.of(
+ Key.CELL_STATS_END, Key.CELL_PROCESSED_CELLS, Key.CELL_QUEUED_CELLS,
+ Key.CELL_TIME_IN_QUEUE, Key.CELL_CIRCUITS_PER_DECILE);
+ Set<Key> connBiDirectStatsKeys = EnumSet.of(Key.CONN_BI_DIRECT);
+ Set<Key> exitStatsKeys = EnumSet.of(
+ Key.EXIT_STATS_END, Key.EXIT_KIBIBYTES_WRITTEN, Key.EXIT_KIBIBYTES_READ,
+ Key.EXIT_STREAMS_OPENED);
+ Set<Key> bridgeStatsKeys = EnumSet.of(
+ Key.BRIDGE_STATS_END, Key.BRIDGE_IPS);
+ atMostOnceKeys.addAll(dirreqStatsKeys);
+ atMostOnceKeys.addAll(entryStatsKeys);
+ atMostOnceKeys.addAll(cellStatsKeys);
+ atMostOnceKeys.addAll(connBiDirectStatsKeys);
+ atMostOnceKeys.addAll(exitStatsKeys);
+ atMostOnceKeys.addAll(bridgeStatsKeys);
+ this.checkAtMostOnceKeys(atMostOnceKeys);
+ this.checkKeysDependOn(dirreqStatsKeys, Key.DIRREQ_STATS_END);
+ this.checkKeysDependOn(entryStatsKeys, Key.ENTRY_STATS_END);
+ this.checkKeysDependOn(cellStatsKeys, Key.CELL_STATS_END);
+ this.checkKeysDependOn(exitStatsKeys, Key.EXIT_STATS_END);
+ this.checkKeysDependOn(bridgeStatsKeys, Key.BRIDGE_STATS_END);
+ this.checkFirstKey(Key.EXTRA_INFO);
+ this.clearParsedKeys();
return;
}
private void parseDescriptorBytes() throws DescriptorParseException {
Scanner scanner = new Scanner(new String(this.rawDescriptorBytes))
- .useDelimiter("\n");
- String nextCrypto = "";
+ .useDelimiter(NL);
+ Key nextCrypto = Key.EMPTY;
List<String> cryptoLines = null;
while (scanner.hasNext()) {
String line = scanner.next();
- String lineNoOpt = line.startsWith("opt ")
- ? line.substring("opt ".length()) : line;
+ String lineNoOpt = line.startsWith(Key.OPT.keyword + SP)
+ ? line.substring(Key.OPT.keyword.length() + 1) : line;
String[] partsNoOpt = lineNoOpt.split("[ \t]+");
- String keyword = partsNoOpt[0];
- switch (keyword) {
- case "extra-info":
+ Key key = Key.get(partsNoOpt[0]);
+ switch (key) {
+ case EXTRA_INFO:
this.parseExtraInfoLine(line, lineNoOpt, partsNoOpt);
break;
- case "published":
+ case PUBLISHED:
this.parsePublishedLine(line, lineNoOpt, partsNoOpt);
break;
- case "read-history":
+ case READ_HISTORY:
this.parseReadHistoryLine(line, lineNoOpt, partsNoOpt);
break;
- case "write-history":
+ case WRITE_HISTORY:
this.parseWriteHistoryLine(line, lineNoOpt, partsNoOpt);
break;
- case "geoip-db-digest":
+ case GEOIP_DB_DIGEST:
this.parseGeoipDbDigestLine(line, lineNoOpt, partsNoOpt);
break;
- case "geoip6-db-digest":
+ case GEOIP6_DB_DIGEST:
this.parseGeoip6DbDigestLine(line, lineNoOpt, partsNoOpt);
break;
- case "geoip-start-time":
+ case GEOIP_START_TIME:
this.parseGeoipStartTimeLine(line, lineNoOpt, partsNoOpt);
break;
- case "geoip-client-origins":
+ case GEOIP_CLIENT_ORIGINS:
this.parseGeoipClientOriginsLine(line, lineNoOpt, partsNoOpt);
break;
- case "dirreq-stats-end":
+ case DIRREQ_STATS_END:
this.parseDirreqStatsEndLine(line, lineNoOpt, partsNoOpt);
break;
- case "dirreq-v2-ips":
+ case DIRREQ_V2_IPS:
this.parseDirreqV2IpsLine(line, lineNoOpt, partsNoOpt);
break;
- case "dirreq-v3-ips":
+ case DIRREQ_V3_IPS:
this.parseDirreqV3IpsLine(line, lineNoOpt, partsNoOpt);
break;
- case "dirreq-v2-reqs":
+ case DIRREQ_V2_REQS:
this.parseDirreqV2ReqsLine(line, lineNoOpt, partsNoOpt);
break;
- case "dirreq-v3-reqs":
+ case DIRREQ_V3_REQS:
this.parseDirreqV3ReqsLine(line, lineNoOpt, partsNoOpt);
break;
- case "dirreq-v2-share":
+ case DIRREQ_V2_SHARE:
this.parseDirreqV2ShareLine(line, lineNoOpt, partsNoOpt);
break;
- case "dirreq-v3-share":
+ case DIRREQ_V3_SHARE:
this.parseDirreqV3ShareLine(line, lineNoOpt, partsNoOpt);
break;
- case "dirreq-v2-resp":
+ case DIRREQ_V2_RESP:
this.parseDirreqV2RespLine(line, lineNoOpt, partsNoOpt);
break;
- case "dirreq-v3-resp":
+ case DIRREQ_V3_RESP:
this.parseDirreqV3RespLine(line, lineNoOpt, partsNoOpt);
break;
- case "dirreq-v2-direct-dl":
+ case DIRREQ_V2_DIRECT_DL:
this.parseDirreqV2DirectDlLine(line, lineNoOpt, partsNoOpt);
break;
- case "dirreq-v3-direct-dl":
+ case DIRREQ_V3_DIRECT_DL:
this.parseDirreqV3DirectDlLine(line, lineNoOpt, partsNoOpt);
break;
- case "dirreq-v2-tunneled-dl":
+ case DIRREQ_V2_TUNNELED_DL:
this.parseDirreqV2TunneledDlLine(line, lineNoOpt, partsNoOpt);
break;
- case "dirreq-v3-tunneled-dl":
+ case DIRREQ_V3_TUNNELED_DL:
this.parseDirreqV3TunneledDlLine(line, lineNoOpt, partsNoOpt);
break;
- case "dirreq-read-history":
+ case DIRREQ_READ_HISTORY:
this.parseDirreqReadHistoryLine(line, lineNoOpt, partsNoOpt);
break;
- case "dirreq-write-history":
+ case DIRREQ_WRITE_HISTORY:
this.parseDirreqWriteHistoryLine(line, lineNoOpt, partsNoOpt);
break;
- case "entry-stats-end":
+ case ENTRY_STATS_END:
this.parseEntryStatsEndLine(line, lineNoOpt, partsNoOpt);
break;
- case "entry-ips":
+ case ENTRY_IPS:
this.parseEntryIpsLine(line, lineNoOpt, partsNoOpt);
break;
- case "cell-stats-end":
+ case CELL_STATS_END:
this.parseCellStatsEndLine(line, lineNoOpt, partsNoOpt);
break;
- case "cell-processed-cells":
+ case CELL_PROCESSED_CELLS:
this.parseCellProcessedCellsLine(line, lineNoOpt, partsNoOpt);
break;
- case "cell-queued-cells":
+ case CELL_QUEUED_CELLS:
this.parseCellQueuedCellsLine(line, lineNoOpt, partsNoOpt);
break;
- case "cell-time-in-queue":
+ case CELL_TIME_IN_QUEUE:
this.parseCellTimeInQueueLine(line, lineNoOpt, partsNoOpt);
break;
- case "cell-circuits-per-decile":
+ case CELL_CIRCUITS_PER_DECILE:
this.parseCellCircuitsPerDecileLine(line, lineNoOpt,
partsNoOpt);
break;
- case "conn-bi-direct":
+ case CONN_BI_DIRECT:
this.parseConnBiDirectLine(line, lineNoOpt, partsNoOpt);
break;
- case "exit-stats-end":
+ case EXIT_STATS_END:
this.parseExitStatsEndLine(line, lineNoOpt, partsNoOpt);
break;
- case "exit-kibibytes-written":
+ case EXIT_KIBIBYTES_WRITTEN:
this.parseExitKibibytesWrittenLine(line, lineNoOpt, partsNoOpt);
break;
- case "exit-kibibytes-read":
+ case EXIT_KIBIBYTES_READ:
this.parseExitKibibytesReadLine(line, lineNoOpt, partsNoOpt);
break;
- case "exit-streams-opened":
+ case EXIT_STREAMS_OPENED:
this.parseExitStreamsOpenedLine(line, lineNoOpt, partsNoOpt);
break;
- case "bridge-stats-end":
+ case BRIDGE_STATS_END:
this.parseBridgeStatsEndLine(line, lineNoOpt, partsNoOpt);
break;
- case "bridge-ips":
+ case BRIDGE_IPS:
this.parseBridgeStatsIpsLine(line, lineNoOpt, partsNoOpt);
break;
- case "bridge-ip-versions":
+ case BRIDGE_IP_VERSIONS:
this.parseBridgeIpVersionsLine(line, lineNoOpt, partsNoOpt);
break;
- case "bridge-ip-transports":
+ case BRIDGE_IP_TRANSPORTS:
this.parseBridgeIpTransportsLine(line, lineNoOpt, partsNoOpt);
break;
- case "transport":
+ case TRANSPORT:
this.parseTransportLine(line, lineNoOpt, partsNoOpt);
break;
- case "hidserv-stats-end":
+ case HIDSERV_STATS_END:
this.parseHidservStatsEndLine(line, lineNoOpt, partsNoOpt);
break;
- case "hidserv-rend-relayed-cells":
+ case HIDSERV_REND_RELAYED_CELLS:
this.parseHidservRendRelayedCellsLine(line, lineNoOpt,
partsNoOpt);
break;
- case "hidserv-dir-onions-seen":
+ case HIDSERV_DIR_ONIONS_SEEN:
this.parseHidservDirOnionsSeenLine(line, lineNoOpt, partsNoOpt);
break;
- case "padding-counts":
+ case PADDING_COUNTS:
this.parsePaddingCountsLine(line, lineNoOpt, partsNoOpt);
break;
- case "identity-ed25519":
+ case IDENTITY_ED25519:
this.parseIdentityEd25519Line(line, lineNoOpt, partsNoOpt);
- nextCrypto = "identity-ed25519";
+ nextCrypto = key;
break;
- case "master-key-ed25519":
+ case MASTER_KEY_ED25519:
this.parseMasterKeyEd25519Line(line, lineNoOpt, partsNoOpt);
break;
- case "router-sig-ed25519":
+ case ROUTER_SIG_ED25519:
this.parseRouterSigEd25519Line(line, lineNoOpt, partsNoOpt);
break;
- case "router-signature":
+ case ROUTER_SIGNATURE:
this.parseRouterSignatureLine(line, lineNoOpt, partsNoOpt);
- nextCrypto = "router-signature";
+ nextCrypto = key;
break;
- case "router-digest":
+ case ROUTER_DIGEST:
this.parseRouterDigestLine(line, lineNoOpt, partsNoOpt);
break;
- case "router-digest-sha256":
+ case ROUTER_DIGEST_SHA256:
this.parseRouterDigestSha256Line(line, lineNoOpt, partsNoOpt);
break;
- case "-----BEGIN":
+ case CRYPTO_BEGIN:
cryptoLines = new ArrayList<>();
cryptoLines.add(line);
break;
- case "-----END":
+ case CRYPTO_END:
cryptoLines.add(line);
StringBuilder sb = new StringBuilder();
for (String cryptoLine : cryptoLines) {
- sb.append("\n").append(cryptoLine);
+ sb.append(NL).append(cryptoLine);
}
String cryptoString = sb.toString().substring(1);
switch (nextCrypto) {
- case "router-signature":
+ case ROUTER_SIGNATURE:
this.routerSignature = cryptoString;
break;
- case "identity-ed25519":
+ case IDENTITY_ED25519:
this.identityEd25519 = cryptoString;
this.parseIdentityEd25519CryptoBlock(cryptoString);
break;
@@ -276,7 +278,7 @@ public abstract class ExtraInfoDescriptorImpl extends DescriptorImpl
}
}
cryptoLines = null;
- nextCrypto = "";
+ nextCrypto = Key.EMPTY;
break;
default:
if (cryptoLines != null) {
@@ -845,8 +847,8 @@ public abstract class ExtraInfoDescriptorImpl extends DescriptorImpl
}
try {
String ascii = new String(this.getRawDescriptorBytes(), "US-ASCII");
- String startToken = "extra-info ";
- String sigToken = "\nrouter-signature\n";
+ String startToken = Key.EXTRA_INFO.keyword + SP;
+ String sigToken = NL + Key.ROUTER_SIGNATURE.keyword + NL;
int start = ascii.indexOf(startToken);
int sig = ascii.indexOf(sigToken) + sigToken.length();
if (start >= 0 && sig >= 0 && sig > start) {
@@ -876,7 +878,7 @@ public abstract class ExtraInfoDescriptorImpl extends DescriptorImpl
}
try {
String ascii = new String(this.getRawDescriptorBytes(), "US-ASCII");
- String startToken = "extra-info ";
+ String startToken = Key.EXTRA_INFO.keyword + SP;
String sigToken = "\n-----END SIGNATURE-----\n";
int start = ascii.indexOf(startToken);
int sig = ascii.indexOf(sigToken) + sigToken.length();
diff --git a/src/main/java/org/torproject/descriptor/impl/Key.java b/src/main/java/org/torproject/descriptor/impl/Key.java
new file mode 100644
index 0000000..763ecbf
--- /dev/null
+++ b/src/main/java/org/torproject/descriptor/impl/Key.java
@@ -0,0 +1,177 @@
+package org.torproject.descriptor.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum Key {
+
+ EMPTY("the-empty-key"),
+ INVALID("the-invalid-key"),
+
+ /* crypto keys */
+ CRYPTO_BEGIN("-----BEGIN"),
+ CRYPTO_END("-----END"),
+
+ /* descriptor keys (in alphabetic order) */
+ A("a"),
+ ACCEPT("accept"),
+ ALLOW_SINGLE_HOP_EXITS("allow-single-hop-exits"),
+ BANDWIDTH("bandwidth"),
+ BANDWIDTH_WEIGHTS("bandwidth-weights"),
+ BRIDGE_IPS("bridge-ips"),
+ BRIDGE_IP_TRANSPORTS("bridge-ip-transports"),
+ BRIDGE_IP_VERSIONS("bridge-ip-versions"),
+ BRIDGE_POOL_ASSIGNMENT("bridge-pool-assignment"),
+ BRIDGE_STATS_END("bridge-stats-end"),
+ CACHES_EXTRA_INFO("caches-extra-info"),
+ CELL_CIRCUITS_PER_DECILE("cell-circuits-per-decile"),
+ CELL_PROCESSED_CELLS("cell-processed-cells"),
+ CELL_QUEUED_CELLS("cell-queued-cells"),
+ CELL_STATS_END("cell-stats-end"),
+ CELL_TIME_IN_QUEUE("cell-time-in-queue"),
+ CLIENT_VERSIONS("client-versions"),
+ CONN_BI_DIRECT("conn-bi-direct"),
+ CONSENSUS_METHOD("consensus-method"),
+ CONSENSUS_METHODS("consensus-methods"),
+ CONTACT("contact"),
+ DIRCACHEPORT("dircacheport"),
+ DIRECTORY_FOOTER("directory-footer"),
+ DIRECTORY_SIGNATURE("directory-signature"),
+ DIRREQ_READ_HISTORY("dirreq-read-history"),
+ DIRREQ_STATS_END("dirreq-stats-end"),
+ DIRREQ_V2_DIRECT_DL("dirreq-v2-direct-dl"),
+ DIRREQ_V2_IPS("dirreq-v2-ips"),
+ DIRREQ_V2_REQS("dirreq-v2-reqs"),
+ DIRREQ_V2_RESP("dirreq-v2-resp"),
+ DIRREQ_V2_SHARE("dirreq-v2-share"),
+ DIRREQ_V2_TUNNELED_DL("dirreq-v2-tunneled-dl"),
+ DIRREQ_V3_DIRECT_DL("dirreq-v3-direct-dl"),
+ DIRREQ_V3_IPS("dirreq-v3-ips"),
+ DIRREQ_V3_REQS("dirreq-v3-reqs"),
+ DIRREQ_V3_RESP("dirreq-v3-resp"),
+ DIRREQ_V3_SHARE("dirreq-v3-share"),
+ DIRREQ_V3_TUNNELED_DL("dirreq-v3-tunneled-dl"),
+ DIRREQ_WRITE_HISTORY("dirreq-write-history"),
+ DIR_ADDRESS("dir-address"),
+ DIR_IDENTITY_KEY("dir-identity-key"),
+ DIR_KEY_CERTIFICATE_VERSION("dir-key-certificate-version"),
+ DIR_KEY_CERTIFICATION("dir-key-certification"),
+ DIR_KEY_CROSSCERT("dir-key-crosscert"),
+ DIR_KEY_EXPIRES("dir-key-expires"),
+ DIR_KEY_PUBLISHED("dir-key-published"),
+ DIR_OPTIONS("dir-options"),
+ DIR_SIGNING_KEY("dir-signing-key"),
+ DIR_SOURCE("dir-source"),
+ ENTRY_IPS("entry-ips"),
+ ENTRY_STATS_END("entry-stats-end"),
+ EVENTDNS("eventdns"),
+ EXIT_KIBIBYTES_READ("exit-kibibytes-read"),
+ EXIT_KIBIBYTES_WRITTEN("exit-kibibytes-written"),
+ EXIT_STATS_END("exit-stats-end"),
+ EXIT_STREAMS_OPENED("exit-streams-opened"),
+ EXTRA_INFO("extra-info"),
+ EXTRA_INFO_DIGEST("extra-info-digest"),
+ FAMILY("family"),
+ FINGERPRINT("fingerprint"),
+ FLAG_THRESHOLDS("flag-thresholds"),
+ FRESH_UNTIL("fresh-until"),
+ GEOIP6_DB_DIGEST("geoip6-db-digest"),
+ GEOIP_CLIENT_ORIGINS("geoip-client-origins"),
+ GEOIP_DB_DIGEST("geoip-db-digest"),
+ GEOIP_START_TIME("geoip-start-time"),
+ HIBERNATING("hibernating"),
+ HIDDEN_SERVICE_DIR("hidden-service-dir"),
+ HIDSERV_DIR_ONIONS_SEEN("hidserv-dir-onions-seen"),
+ HIDSERV_REND_RELAYED_CELLS("hidserv-rend-relayed-cells"),
+ HIDSERV_STATS_END("hidserv-stats-end"),
+ ID("id"),
+ IDENTITY_ED25519("identity-ed25519"),
+ IPV6_POLICY("ipv6-policy"),
+ KNOWN_FLAGS("known-flags"),
+ LEGACY_DIR_KEY("legacy-dir-key"),
+ LEGACY_KEY("legacy-key"),
+ M("m"),
+ MASTER_KEY_ED25519("master-key-ed25519"),
+ NETWORK_STATUS_VERSION("network-status-version"),
+ NTOR_ONION_KEY("ntor-onion-key"),
+ NTOR_ONION_KEY_CROSSCERT("ntor-onion-key-crosscert"),
+ ONION_KEY("onion-key"),
+ ONION_KEY_CROSSCERT("onion-key-crosscert"),
+ OPT("opt"),
+ OR_ADDRESS("or-address"),
+ P("p"),
+ P6("p6"),
+ PACKAGE("package"),
+ PADDING_COUNTS("padding-counts"),
+ PARAMS("params"),
+ PLATFORM("platform"),
+ PR("pr"),
+ PROTO("proto"),
+ PROTOCOLS("protocols"),
+ PUBLISHED("published"),
+ R("r"),
+ READ_HISTORY("read-history"),
+ RECOMMENDED_CLIENT_PROTOCOLS("recommended-client-protocols"),
+ RECOMMENDED_RELAY_PROTOCOLS("recommended-relay-protocols"),
+ RECOMMENDED_SOFTWARE("recommended-software"),
+ REJECT("reject"),
+ REQUIRED_CLIENT_PROTOCOLS("required-client-protocols"),
+ REQUIRED_RELAY_PROTOCOLS("required-relay-protocols"),
+ ROUTER("router"),
+ ROUTER_DIGEST("router-digest"),
+ ROUTER_DIGEST_SHA256("router-digest-sha256"),
+ ROUTER_SIGNATURE("router-signature"),
+ ROUTER_SIG_ED25519("router-sig-ed25519"),
+ ROUTER_STATUS("router-status"),
+ RUNNING_ROUTERS("running-routers"),
+ S("s"),
+ SERVER_VERSIONS("server-versions"),
+ SHARED_RAND_COMMIT("shared-rand-commit"),
+ SHARED_RAND_CURRENT_VALUE("shared-rand-current-value"),
+ SHARED_RAND_PARTICIPATE("shared-rand-participate"),
+ SHARED_RAND_PREVIOUS_VALUE("shared-rand-previous-value"),
+ SIGNED_DIRECTORY("signed-directory"),
+ SIGNING_KEY("signing-key"),
+ TRANSPORT("transport"),
+ TUNNELLED_DIR_SERVER("tunnelled-dir-server"),
+ UPTIME("uptime"),
+ V("v"),
+ VALID_AFTER("valid-after"),
+ VALID_UNTIL("valid-until"),
+ VOTE_DIGEST("vote-digest"),
+ VOTE_STATUS("vote-status"),
+ VOTING_DELAY("voting-delay"),
+ W("w"),
+ WRITE_HISTORY("write-history");
+
+ /** The keyword as it appears in descriptors. */
+ public final String keyword;
+
+ private static final Map<String, Key> keywordMap = new HashMap<>();
+ static {
+ for (Key key : values()) {
+ keywordMap.put(key.keyword, key);
+ }
+ keywordMap.remove(INVALID.keyword);
+ keywordMap.remove(EMPTY.keyword);
+ }
+
+ private Key(String keyword) {
+ this.keyword = keyword;
+ }
+
+ /** Retrieve a Key for a keyword.
+ * Returns Key.INVALID for non-existing keywords. */
+ public static Key get(String keyword) {
+ Key res = INVALID;
+ try {
+ res = keywordMap.get(keyword);
+ } catch (Throwable th) {
+ res = INVALID;
+ }
+ if (null == res) {
+ res = INVALID;
+ }
+ return res;
+ }
+}
diff --git a/src/main/java/org/torproject/descriptor/impl/MicrodescriptorImpl.java b/src/main/java/org/torproject/descriptor/impl/MicrodescriptorImpl.java
index 5c94371..e8329cc 100644
--- a/src/main/java/org/torproject/descriptor/impl/MicrodescriptorImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/MicrodescriptorImpl.java
@@ -11,7 +11,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashSet;
+import java.util.EnumSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
@@ -28,7 +28,7 @@ public class MicrodescriptorImpl extends DescriptorImpl
List<Microdescriptor> parsedDescriptors = new ArrayList<>();
List<byte[]> splitDescriptorsBytes =
DescriptorImpl.splitRawDescriptorBytes(descriptorsBytes,
- "onion-key\n");
+ Key.ONION_KEY + NL);
for (byte[] descriptorBytes : splitDescriptorsBytes) {
Microdescriptor parsedDescriptor =
new MicrodescriptorImpl(descriptorBytes,
@@ -44,21 +44,19 @@ public class MicrodescriptorImpl extends DescriptorImpl
super(descriptorBytes, failUnrecognizedDescriptorLines, false);
this.parseDescriptorBytes();
this.calculateDigest();
- Set<String> exactlyOnceKeywords = new HashSet<>(Arrays.asList(
- "onion-key".split(",")));
- this.checkExactlyOnceKeywords(exactlyOnceKeywords);
- Set<String> atMostOnceKeywords = new HashSet<>(Arrays.asList((
- "ntor-onion-key,family,p,p6,id").split(",")));
- this.checkAtMostOnceKeywords(atMostOnceKeywords);
- this.checkFirstKeyword("onion-key");
- this.clearParsedKeywords();
+ this.checkExactlyOnceKeys(EnumSet.of(Key.ONION_KEY));
+ Set<Key> atMostOnceKeys = EnumSet.of(
+ Key.NTOR_ONION_KEY, Key.FAMILY, Key.P, Key.P6, Key.ID);
+ this.checkAtMostOnceKeys(atMostOnceKeys);
+ this.checkFirstKey(Key.ONION_KEY);
+ this.clearParsedKeys();
return;
}
private void parseDescriptorBytes() throws DescriptorParseException {
Scanner scanner = new Scanner(new String(this.rawDescriptorBytes))
- .useDelimiter("\n");
- String nextCrypto = "";
+ .useDelimiter(NL);
+ Key nextCrypto = Key.EMPTY;
StringBuilder crypto = null;
while (scanner.hasNext()) {
String line = scanner.next();
@@ -66,49 +64,49 @@ public class MicrodescriptorImpl extends DescriptorImpl
continue;
}
String[] parts = line.split("[ \t]+");
- String keyword = parts[0];
- switch (keyword) {
- case "onion-key":
+ Key key = Key.get(parts[0]);
+ switch (key) {
+ case ONION_KEY:
this.parseOnionKeyLine(line, parts);
- nextCrypto = "onion-key";
+ nextCrypto = key;
break;
- case "ntor-onion-key":
+ case NTOR_ONION_KEY:
this.parseNtorOnionKeyLine(line, parts);
break;
- case "a":
+ case A:
this.parseALine(line, parts);
break;
- case "family":
+ case FAMILY:
this.parseFamilyLine(line, parts);
break;
- case "p":
+ case P:
this.parsePLine(line, parts);
break;
- case "p6":
+ case P6:
this.parseP6Line(line, parts);
break;
- case "id":
+ case ID:
this.parseIdLine(line, parts);
break;
- case "-----BEGIN":
+ case CRYPTO_BEGIN:
crypto = new StringBuilder();
- crypto.append(line).append("\n");
+ crypto.append(line).append(NL);
break;
- case "-----END":
- crypto.append(line).append("\n");
+ case CRYPTO_END:
+ crypto.append(line).append(NL);
String cryptoString = crypto.toString();
crypto = null;
- if (nextCrypto.equals("onion-key")) {
+ if (nextCrypto.equals(Key.ONION_KEY)) {
this.onionKey = cryptoString;
} else {
throw new DescriptorParseException("Unrecognized crypto "
+ "block in microdescriptor.");
}
- nextCrypto = "";
+ nextCrypto = Key.EMPTY;
break;
default:
if (crypto != null) {
- crypto.append(line).append("\n");
+ crypto.append(line).append(NL);
} else {
ParseHelper.parseKeyword(line, parts[0]);
if (this.failUnrecognizedDescriptorLines) {
diff --git a/src/main/java/org/torproject/descriptor/impl/NetworkStatusEntryImpl.java b/src/main/java/org/torproject/descriptor/impl/NetworkStatusEntryImpl.java
index 152546a..cb4eca8 100644
--- a/src/main/java/org/torproject/descriptor/impl/NetworkStatusEntryImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/NetworkStatusEntryImpl.java
@@ -3,11 +3,15 @@
package org.torproject.descriptor.impl;
+import static org.torproject.descriptor.impl.DescriptorImpl.NL;
+import static org.torproject.descriptor.impl.DescriptorImpl.SP;
+
import org.torproject.descriptor.DescriptorParseException;
import org.torproject.descriptor.NetworkStatusEntry;
import java.util.ArrayList;
import java.util.BitSet;
+import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -46,34 +50,25 @@ public class NetworkStatusEntryImpl implements NetworkStatusEntry {
this.microdescConsensus = microdescConsensus;
this.failUnrecognizedDescriptorLines =
failUnrecognizedDescriptorLines;
- this.initializeKeywords();
this.parseStatusEntryBytes();
- this.clearAtMostOnceKeywords();
+ this.clearAtMostOnceKeys();
}
- private SortedSet<String> atMostOnceKeywords;
-
- private void initializeKeywords() {
- this.atMostOnceKeywords = new TreeSet<>();
- this.atMostOnceKeywords.add("s");
- this.atMostOnceKeywords.add("v");
- this.atMostOnceKeywords.add("pr");
- this.atMostOnceKeywords.add("w");
- this.atMostOnceKeywords.add("p");
- }
+ private Set<Key> atMostOnceKeys = EnumSet.of(
+ Key.S, Key.V, Key.PR, Key.W, Key.P);
- private void parsedAtMostOnceKeyword(String keyword)
+ private void parsedAtMostOnceKey(Key key)
throws DescriptorParseException {
- if (!this.atMostOnceKeywords.contains(keyword)) {
- throw new DescriptorParseException("Duplicate '" + keyword
+ if (!this.atMostOnceKeys.contains(key)) {
+ throw new DescriptorParseException("Duplicate '" + key.keyword
+ "' line in status entry.");
}
- this.atMostOnceKeywords.remove(keyword);
+ this.atMostOnceKeys.remove(key);
}
private void parseStatusEntryBytes() throws DescriptorParseException {
Scanner scanner = new Scanner(new String(this.statusEntryBytes))
- .useDelimiter("\n");
+ .useDelimiter(NL);
String line = null;
if (!scanner.hasNext() || !(line = scanner.next()).startsWith("r ")) {
throw new DescriptorParseException("Status entry must start with "
@@ -83,32 +78,33 @@ public class NetworkStatusEntryImpl implements NetworkStatusEntry {
this.parseRLine(line, rlineParts);
while (scanner.hasNext()) {
line = scanner.next();
- String[] parts = !line.startsWith("opt ") ? line.split("[ \t]+")
- : line.substring("opt ".length()).split("[ \t]+");
- String keyword = parts[0];
- switch (keyword) {
- case "a":
+ String[] parts = !line.startsWith(Key.OPT.keyword + SP)
+ ? line.split("[ \t]+")
+ : line.substring(Key.OPT.keyword.length() + 1).split("[ \t]+");
+ Key key = Key.get(parts[0]);
+ switch (key) {
+ case A:
this.parseALine(line, parts);
break;
- case "s":
+ case S:
this.parseSLine(line, parts);
break;
- case "v":
+ case V:
this.parseVLine(line, parts);
break;
- case "pr":
+ case PR:
this.parsePrLine(line, parts);
break;
- case "w":
+ case W:
this.parseWLine(line, parts);
break;
- case "p":
+ case P:
this.parsePLine(line, parts);
break;
- case "m":
+ case M:
this.parseMLine(line, parts);
break;
- case "id":
+ case ID:
this.parseIdLine(line, parts);
break;
default:
@@ -167,7 +163,7 @@ public class NetworkStatusEntryImpl implements NetworkStatusEntry {
private void parseSLine(String line, String[] parts)
throws DescriptorParseException {
- this.parsedAtMostOnceKeyword("s");
+ this.parsedAtMostOnceKey(Key.S);
BitSet flags = new BitSet(flagIndexes.size());
for (int i = 1; i < parts.length; i++) {
String flag = parts[i];
@@ -182,9 +178,9 @@ public class NetworkStatusEntryImpl implements NetworkStatusEntry {
private void parseVLine(String line, String[] parts)
throws DescriptorParseException {
- this.parsedAtMostOnceKeyword("v");
+ this.parsedAtMostOnceKey(Key.V);
String noOptLine = line;
- if (noOptLine.startsWith("opt ")) {
+ if (noOptLine.startsWith(Key.OPT.keyword + SP)) {
noOptLine = noOptLine.substring(4);
}
if (noOptLine.length() < 3) {
@@ -197,13 +193,13 @@ public class NetworkStatusEntryImpl implements NetworkStatusEntry {
private void parsePrLine(String line, String[] parts)
throws DescriptorParseException {
- this.parsedAtMostOnceKeyword("pr");
+ this.parsedAtMostOnceKey(Key.PR);
this.protocols = ParseHelper.parseProtocolVersions(line, line, parts);
}
private void parseWLine(String line, String[] parts)
throws DescriptorParseException {
- this.parsedAtMostOnceKeyword("w");
+ this.parsedAtMostOnceKey(Key.W);
SortedMap<String, Integer> pairs =
ParseHelper.parseKeyValueIntegerPairs(line, parts, 1, "=");
if (pairs.isEmpty()) {
@@ -225,7 +221,7 @@ public class NetworkStatusEntryImpl implements NetworkStatusEntry {
private void parsePLine(String line, String[] parts)
throws DescriptorParseException {
- this.parsedAtMostOnceKeyword("p");
+ this.parsedAtMostOnceKey(Key.P);
boolean isValid = true;
if (parts.length != 3) {
isValid = false;
@@ -280,8 +276,8 @@ public class NetworkStatusEntryImpl implements NetworkStatusEntry {
}
}
- private void clearAtMostOnceKeywords() {
- this.atMostOnceKeywords = null;
+ private void clearAtMostOnceKeys() {
+ this.atMostOnceKeys = null;
}
private String nickname;
diff --git a/src/main/java/org/torproject/descriptor/impl/NetworkStatusImpl.java b/src/main/java/org/torproject/descriptor/impl/NetworkStatusImpl.java
index e3891a6..f67c32a 100644
--- a/src/main/java/org/torproject/descriptor/impl/NetworkStatusImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/NetworkStatusImpl.java
@@ -34,15 +34,16 @@ public abstract class NetworkStatusImpl extends DescriptorImpl {
throw new DescriptorParseException("Descriptor is empty.");
}
String descriptorString = new String(rawDescriptorBytes);
- int firstRIndex = this.findFirstIndexOfKeyword(descriptorString, "r");
+ int firstRIndex = this.findFirstIndexOfKeyword(descriptorString,
+ Key.R.keyword);
int endIndex = descriptorString.length();
int firstDirectorySignatureIndex = this.findFirstIndexOfKeyword(
- descriptorString, "directory-signature");
+ descriptorString, Key.DIRECTORY_SIGNATURE.keyword);
if (firstDirectorySignatureIndex < 0) {
firstDirectorySignatureIndex = endIndex;
}
int directoryFooterIndex = this.findFirstIndexOfKeyword(
- descriptorString, "directory-footer");
+ descriptorString, Key.DIRECTORY_FOOTER.keyword);
if (directoryFooterIndex < 0) {
directoryFooterIndex = firstDirectorySignatureIndex;
}
@@ -50,7 +51,8 @@ public abstract class NetworkStatusImpl extends DescriptorImpl {
firstRIndex = directoryFooterIndex;
}
int firstDirSourceIndex = !containsDirSourceEntries ? -1
- : this.findFirstIndexOfKeyword(descriptorString, "dir-source");
+ : this.findFirstIndexOfKeyword(descriptorString,
+ Key.DIR_SOURCE.keyword);
if (firstDirSourceIndex < 0) {
firstDirSourceIndex = firstRIndex;
}
@@ -79,10 +81,10 @@ public abstract class NetworkStatusImpl extends DescriptorImpl {
String keyword) {
if (descriptorString.startsWith(keyword)) {
return 0;
- } else if (descriptorString.contains("\n" + keyword + " ")) {
- return descriptorString.indexOf("\n" + keyword + " ") + 1;
- } else if (descriptorString.contains("\n" + keyword + "\n")) {
- return descriptorString.indexOf("\n" + keyword + "\n") + 1;
+ } else if (descriptorString.contains(NL + keyword + SP)) {
+ return descriptorString.indexOf(NL + keyword + SP) + 1;
+ } else if (descriptorString.contains(NL + keyword + NL)) {
+ return descriptorString.indexOf(NL + keyword + NL) + 1;
} else {
return -1;
}
@@ -99,7 +101,8 @@ public abstract class NetworkStatusImpl extends DescriptorImpl {
private void parseDirSourceBytes(String descriptorString, int start,
int end) throws DescriptorParseException {
List<byte[]> splitDirSourceBytes =
- this.splitByKeyword(descriptorString, "dir-source", start, end);
+ this.splitByKeyword(
+ descriptorString, Key.DIR_SOURCE.keyword, start, end);
for (byte[] dirSourceBytes : splitDirSourceBytes) {
this.parseDirSource(dirSourceBytes);
}
@@ -108,7 +111,7 @@ public abstract class NetworkStatusImpl extends DescriptorImpl {
private void parseStatusEntryBytes(String descriptorString, int start,
int end) throws DescriptorParseException {
List<byte[]> splitStatusEntryBytes =
- this.splitByKeyword(descriptorString, "r", start, end);
+ this.splitByKeyword(descriptorString, Key.R.keyword, start, end);
for (byte[] statusEntryBytes : splitStatusEntryBytes) {
this.parseStatusEntry(statusEntryBytes);
}
@@ -125,7 +128,7 @@ public abstract class NetworkStatusImpl extends DescriptorImpl {
private void parseDirectorySignatureBytes(String descriptorString,
int start, int end) throws DescriptorParseException {
List<byte[]> splitDirectorySignatureBytes = this.splitByKeyword(
- descriptorString, "directory-signature", start, end);
+ descriptorString, Key.DIRECTORY_SIGNATURE.keyword, start, end);
for (byte[] directorySignatureBytes : splitDirectorySignatureBytes) {
this.parseDirectorySignature(directorySignatureBytes);
}
@@ -136,9 +139,9 @@ public abstract class NetworkStatusImpl extends DescriptorImpl {
List<byte[]> splitParts = new ArrayList<>();
int from = start;
while (from < end) {
- int to = descriptorString.indexOf("\n" + keyword + " ", from);
+ int to = descriptorString.indexOf(NL + keyword + SP, from);
if (to < 0) {
- to = descriptorString.indexOf("\n" + keyword + "\n", from);
+ to = descriptorString.indexOf(NL + keyword + NL, from);
}
if (to < 0) {
to = end;
diff --git a/src/main/java/org/torproject/descriptor/impl/RelayDirectoryImpl.java b/src/main/java/org/torproject/descriptor/impl/RelayDirectoryImpl.java
index fc8f07b..fae54f4 100644
--- a/src/main/java/org/torproject/descriptor/impl/RelayDirectoryImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/RelayDirectoryImpl.java
@@ -12,8 +12,7 @@ import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
+import java.util.EnumSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
@@ -29,7 +28,7 @@ public class RelayDirectoryImpl extends DescriptorImpl
List<RelayDirectory> parsedDirectories = new ArrayList<>();
List<byte[]> splitDirectoriesBytes =
DescriptorImpl.splitRawDescriptorBytes(directoriesBytes,
- "signed-directory\n");
+ Key.SIGNED_DIRECTORY.keyword + NL);
for (byte[] directoryBytes : splitDirectoriesBytes) {
RelayDirectory parsedDirectory =
new RelayDirectoryImpl(directoryBytes,
@@ -45,28 +44,28 @@ public class RelayDirectoryImpl extends DescriptorImpl
super(directoryBytes, failUnrecognizedDescriptorLines, true);
this.splitAndParseParts(rawDescriptorBytes);
this.calculateDigest();
- Set<String> exactlyOnceKeywords = new HashSet<>(Arrays.asList((
- "signed-directory,recommended-software,"
- + "directory-signature").split(",")));
- this.checkExactlyOnceKeywords(exactlyOnceKeywords);
- Set<String> atMostOnceKeywords = new HashSet<>(Arrays.asList(
- "dir-signing-key,running-routers,router-status".split(",")));
- this.checkAtMostOnceKeywords(atMostOnceKeywords);
- this.checkFirstKeyword("signed-directory");
- this.clearParsedKeywords();
+ Set<Key> exactlyOnceKeys = EnumSet.of(
+ Key.SIGNED_DIRECTORY, Key.RECOMMENDED_SOFTWARE,
+ Key.DIRECTORY_SIGNATURE);
+ this.checkExactlyOnceKeys(exactlyOnceKeys);
+ Set<Key> atMostOnceKeys = EnumSet.of(
+ Key.DIR_SIGNING_KEY, Key.RUNNING_ROUTERS, Key.ROUTER_STATUS);
+ this.checkAtMostOnceKeys(atMostOnceKeys);
+ this.checkFirstKey(Key.SIGNED_DIRECTORY);
+ this.clearParsedKeys();
}
private void calculateDigest() throws DescriptorParseException {
try {
String ascii = new String(this.getRawDescriptorBytes(), "US-ASCII");
- String startToken = "signed-directory\n";
- String sigToken = "\ndirectory-signature ";
+ String startToken = Key.SIGNED_DIRECTORY.keyword + NL;
+ String sigToken = NL + Key.DIRECTORY_SIGNATURE.keyword + SP;
if (!ascii.contains(sigToken)) {
return;
}
int start = ascii.indexOf(startToken);
int sig = ascii.indexOf(sigToken) + sigToken.length();
- sig = ascii.indexOf("\n", sig) + 1;
+ sig = ascii.indexOf(NL, sig) + 1;
if (start >= 0 && sig >= 0 && sig > start) {
byte[] forDigest = new byte[sig - start];
System.arraycopy(this.getRawDescriptorBytes(), start,
@@ -94,9 +93,9 @@ public class RelayDirectoryImpl extends DescriptorImpl
String descriptorString = new String(rawDescriptorBytes);
int startIndex = 0;
int firstRouterIndex = this.findFirstIndexOfKeyword(descriptorString,
- "router");
+ Key.ROUTER.keyword);
int directorySignatureIndex = this.findFirstIndexOfKeyword(
- descriptorString, "directory-signature");
+ descriptorString, Key.DIRECTORY_SIGNATURE.keyword);
int endIndex = descriptorString.length();
if (directorySignatureIndex < 0) {
directorySignatureIndex = endIndex;
@@ -122,10 +121,10 @@ public class RelayDirectoryImpl extends DescriptorImpl
String keyword) {
if (descriptorString.startsWith(keyword)) {
return 0;
- } else if (descriptorString.contains("\n" + keyword + " ")) {
- return descriptorString.indexOf("\n" + keyword + " ") + 1;
- } else if (descriptorString.contains("\n" + keyword + "\n")) {
- return descriptorString.indexOf("\n" + keyword + "\n") + 1;
+ } else if (descriptorString.contains(NL + keyword + SP)) {
+ return descriptorString.indexOf(NL + keyword + SP) + 1;
+ } else if (descriptorString.contains(NL + keyword + NL)) {
+ return descriptorString.indexOf(NL + keyword + NL) + 1;
} else {
return -1;
}
@@ -142,7 +141,7 @@ public class RelayDirectoryImpl extends DescriptorImpl
private void parseServerDescriptorBytes(String descriptorString,
int start, int end) throws DescriptorParseException {
List<byte[]> splitServerDescriptorBytes =
- this.splitByKeyword(descriptorString, "router", start, end);
+ this.splitByKeyword(descriptorString, Key.ROUTER.keyword, start, end);
for (byte[] statusEntryBytes : splitServerDescriptorBytes) {
this.parseServerDescriptor(statusEntryBytes);
}
@@ -162,9 +161,9 @@ public class RelayDirectoryImpl extends DescriptorImpl
List<byte[]> splitParts = new ArrayList<>();
int from = start;
while (from < end) {
- int to = descriptorString.indexOf("\n" + keyword + " ", from);
+ int to = descriptorString.indexOf(NL + keyword + SP, from);
if (to < 0) {
- to = descriptorString.indexOf("\n" + keyword + "\n", from);
+ to = descriptorString.indexOf(NL + keyword + NL, from);
}
if (to < 0) {
to = end;
@@ -187,9 +186,9 @@ public class RelayDirectoryImpl extends DescriptorImpl
private void parseHeader(byte[] headerBytes)
throws DescriptorParseException {
- Scanner scanner = new Scanner(new String(headerBytes)).useDelimiter("\n");
+ Scanner scanner = new Scanner(new String(headerBytes)).useDelimiter(NL);
String publishedLine = null;
- String nextCrypto = "";
+ Key nextCrypto = Key.EMPTY;
String runningRoutersLine = null;
String routerStatusLine = null;
StringBuilder crypto = null;
@@ -198,15 +197,15 @@ public class RelayDirectoryImpl extends DescriptorImpl
if (line.isEmpty() || line.startsWith("@")) {
continue;
}
- String lineNoOpt = line.startsWith("opt ")
- ? line.substring("opt ".length()) : line;
+ String lineNoOpt = line.startsWith(Key.OPT.keyword + SP)
+ ? line.substring(Key.OPT.keyword.length() + 1) : line;
String[] partsNoOpt = lineNoOpt.split("[ \t]+");
- String keyword = partsNoOpt[0];
- switch (keyword) {
- case "signed-directory":
+ Key key = Key.get(partsNoOpt[0]);
+ switch (key) {
+ case SIGNED_DIRECTORY:
this.parseSignedDirectoryLine(line, lineNoOpt, partsNoOpt);
break;
- case "published":
+ case PUBLISHED:
if (publishedLine != null) {
throw new DescriptorParseException("Keyword 'published' is "
+ "contained more than once, but must be contained "
@@ -215,39 +214,39 @@ public class RelayDirectoryImpl extends DescriptorImpl
publishedLine = line;
}
break;
- case "dir-signing-key":
+ case DIR_SIGNING_KEY:
this.parseDirSigningKeyLine(line, lineNoOpt, partsNoOpt);
- nextCrypto = "dir-signing-key";
+ nextCrypto = key;
break;
- case "recommended-software":
+ case RECOMMENDED_SOFTWARE:
this.parseRecommendedSoftwareLine(line, lineNoOpt, partsNoOpt);
break;
- case "running-routers":
+ case RUNNING_ROUTERS:
runningRoutersLine = line;
break;
- case "router-status":
+ case ROUTER_STATUS:
routerStatusLine = line;
break;
- case "-----BEGIN":
+ case CRYPTO_BEGIN:
crypto = new StringBuilder();
- crypto.append(line).append("\n");
+ crypto.append(line).append(NL);
break;
- case "-----END":
- crypto.append(line).append("\n");
+ case CRYPTO_END:
+ crypto.append(line).append(NL);
String cryptoString = crypto.toString();
crypto = null;
- if (nextCrypto.equals("dir-signing-key")
+ if (nextCrypto.equals(Key.DIR_SIGNING_KEY)
&& this.dirSigningKey == null) {
this.dirSigningKey = cryptoString;
} else {
throw new DescriptorParseException("Unrecognized crypto "
+ "block in v1 directory.");
}
- nextCrypto = "";
+ nextCrypto = Key.EMPTY;
break;
default:
if (crypto != null) {
- crypto.append(line).append("\n");
+ crypto.append(line).append(NL);
} else {
if (this.failUnrecognizedDescriptorLines) {
throw new DescriptorParseException("Unrecognized line '"
@@ -265,15 +264,17 @@ public class RelayDirectoryImpl extends DescriptorImpl
throw new DescriptorParseException("Keyword 'published' is "
+ "contained 0 times, but must be contained exactly once.");
} else {
- String publishedLineNoOpt = publishedLine.startsWith("opt ")
- ? publishedLine.substring("opt ".length()) : publishedLine;
+ String publishedLineNoOpt = publishedLine.startsWith(Key.OPT.keyword + SP)
+ ? publishedLine.substring(Key.OPT.keyword.length() + 1)
+ : publishedLine;
String[] publishedPartsNoOpt = publishedLineNoOpt.split("[ \t]+");
this.parsePublishedLine(publishedLine, publishedLineNoOpt,
publishedPartsNoOpt);
}
if (routerStatusLine != null) {
- String routerStatusLineNoOpt = routerStatusLine.startsWith("opt ")
- ? routerStatusLine.substring("opt ".length())
+ String routerStatusLineNoOpt =
+ routerStatusLine.startsWith(Key.OPT.keyword + SP)
+ ? routerStatusLine.substring(Key.OPT.keyword.length() + 1)
: routerStatusLine;
String[] routerStatusPartsNoOpt =
routerStatusLineNoOpt.split("[ \t]+");
@@ -281,8 +282,8 @@ public class RelayDirectoryImpl extends DescriptorImpl
routerStatusPartsNoOpt);
} else if (runningRoutersLine != null) {
String runningRoutersLineNoOpt =
- runningRoutersLine.startsWith("opt ")
- ? runningRoutersLine.substring("opt ".length())
+ runningRoutersLine.startsWith(Key.OPT.keyword + SP)
+ ? runningRoutersLine.substring(Key.OPT.keyword.length() + 1)
: runningRoutersLine;
String[] runningRoutersPartsNoOpt =
runningRoutersLineNoOpt.split("[ \t]+");
@@ -308,39 +309,39 @@ public class RelayDirectoryImpl extends DescriptorImpl
private void parseDirectorySignature(byte[] directorySignatureBytes)
throws DescriptorParseException {
Scanner scanner = new Scanner(new String(directorySignatureBytes))
- .useDelimiter("\n");
- String nextCrypto = "";
+ .useDelimiter(NL);
+ Key nextCrypto = Key.EMPTY;
StringBuilder crypto = null;
while (scanner.hasNext()) {
String line = scanner.next();
- String lineNoOpt = line.startsWith("opt ")
- ? line.substring("opt ".length()) : line;
+ String lineNoOpt = line.startsWith(Key.OPT.keyword + SP)
+ ? line.substring(Key.OPT.keyword.length() + 1) : line;
String[] partsNoOpt = lineNoOpt.split("[ \t]+");
- String keyword = partsNoOpt[0];
- switch (keyword) {
- case "directory-signature":
+ Key key = Key.get(partsNoOpt[0]);
+ switch (key) {
+ case DIRECTORY_SIGNATURE:
this.parseDirectorySignatureLine(line, lineNoOpt, partsNoOpt);
- nextCrypto = "directory-signature";
+ nextCrypto = key;
break;
- case "-----BEGIN":
+ case CRYPTO_BEGIN:
crypto = new StringBuilder();
- crypto.append(line).append("\n");
+ crypto.append(line).append(NL);
break;
- case "-----END":
- crypto.append(line).append("\n");
+ case CRYPTO_END:
+ crypto.append(line).append(NL);
String cryptoString = crypto.toString();
crypto = null;
- if (nextCrypto.equals("directory-signature")) {
+ if (nextCrypto.equals(Key.DIRECTORY_SIGNATURE)) {
this.directorySignature = cryptoString;
} else {
throw new DescriptorParseException("Unrecognized crypto "
+ "block in v2 network status.");
}
- nextCrypto = "";
+ nextCrypto = Key.EMPTY;
break;
default:
if (crypto != null) {
- crypto.append(line).append("\n");
+ crypto.append(line).append(NL);
} else if (this.failUnrecognizedDescriptorLines) {
throw new DescriptorParseException("Unrecognized line '"
+ line + "' in v2 network status.");
@@ -356,7 +357,7 @@ public class RelayDirectoryImpl extends DescriptorImpl
private void parseSignedDirectoryLine(String line, String lineNoOpt,
String[] partsNoOpt) throws DescriptorParseException {
- if (!lineNoOpt.equals("signed-directory")) {
+ if (!lineNoOpt.equals(Key.SIGNED_DIRECTORY.keyword)) {
throw new DescriptorParseException("Illegal line '" + line + "'.");
}
}
@@ -379,11 +380,11 @@ public class RelayDirectoryImpl extends DescriptorImpl
sb.append("-----BEGIN RSA PUBLIC KEY-----\n");
String keyString = partsNoOpt[1];
while (keyString.length() > 64) {
- sb.append(keyString.substring(0, 64)).append("\n");
+ sb.append(keyString.substring(0, 64)).append(NL);
keyString = keyString.substring(64);
}
if (keyString.length() > 0) {
- sb.append(keyString).append("\n");
+ sb.append(keyString).append(NL);
}
sb.append("-----END RSA PUBLIC KEY-----\n");
this.dirSigningKey = sb.toString();
diff --git a/src/main/java/org/torproject/descriptor/impl/RelayExtraInfoDescriptorImpl.java b/src/main/java/org/torproject/descriptor/impl/RelayExtraInfoDescriptorImpl.java
index 3ec4869..6ee86b1 100644
--- a/src/main/java/org/torproject/descriptor/impl/RelayExtraInfoDescriptorImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/RelayExtraInfoDescriptorImpl.java
@@ -19,7 +19,7 @@ public class RelayExtraInfoDescriptorImpl
List<ExtraInfoDescriptor> parsedDescriptors = new ArrayList<>();
List<byte[]> splitDescriptorsBytes =
DescriptorImpl.splitRawDescriptorBytes(descriptorsBytes,
- "extra-info ");
+ Key.EXTRA_INFO.keyword + SP);
for (byte[] descriptorBytes : splitDescriptorsBytes) {
ExtraInfoDescriptor parsedDescriptor =
new RelayExtraInfoDescriptorImpl(descriptorBytes,
diff --git a/src/main/java/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java b/src/main/java/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java
index ef135d4..4570931 100644
--- a/src/main/java/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java
@@ -11,7 +11,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashSet;
+import java.util.EnumSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
@@ -33,7 +33,7 @@ public class RelayNetworkStatusConsensusImpl extends NetworkStatusImpl
new ArrayList<>();
List<byte[]> splitConsensusBytes =
DescriptorImpl.splitRawDescriptorBytes(consensusesBytes,
- "network-status-version 3");
+ Key.NETWORK_STATUS_VERSION.keyword + SP + "3");
for (byte[] consensusBytes : splitConsensusBytes) {
RelayNetworkStatusConsensus parsedConsensus =
new RelayNetworkStatusConsensusImpl(consensusBytes,
@@ -47,27 +47,27 @@ public class RelayNetworkStatusConsensusImpl extends NetworkStatusImpl
boolean failUnrecognizedDescriptorLines)
throws DescriptorParseException {
super(consensusBytes, failUnrecognizedDescriptorLines, true, false);
- Set<String> exactlyOnceKeywords = new HashSet<>(Arrays.asList((
- "vote-status,consensus-method,valid-after,fresh-until,"
- + "valid-until,voting-delay,known-flags").split(",")));
- this.checkExactlyOnceKeywords(exactlyOnceKeywords);
- Set<String> atMostOnceKeywords = new HashSet<>(Arrays.asList((
- "client-versions,server-versions,recommended-client-protocols,"
- + "recommended-relay-protocols,required-client-protocols,"
- + "required-relay-protocols,params,shared-rand-previous-value,"
- + "shared-rand-current-value,directory-footer,bandwidth-weights")
- .split(",")));
- this.checkAtMostOnceKeywords(atMostOnceKeywords);
- this.checkFirstKeyword("network-status-version");
- this.clearParsedKeywords();
+ Set<Key> exactlyOnceKeys = EnumSet.of(
+ Key.VOTE_STATUS, Key.CONSENSUS_METHOD, Key.VALID_AFTER, Key.FRESH_UNTIL,
+ Key.VALID_UNTIL, Key.VOTING_DELAY, Key.KNOWN_FLAGS);
+ this.checkExactlyOnceKeys(exactlyOnceKeys);
+ Set<Key> atMostOnceKeys = EnumSet.of(
+ Key.CLIENT_VERSIONS, Key.SERVER_VERSIONS,
+ Key.RECOMMENDED_CLIENT_PROTOCOLS, Key.RECOMMENDED_RELAY_PROTOCOLS,
+ Key.REQUIRED_CLIENT_PROTOCOLS, Key.REQUIRED_RELAY_PROTOCOLS, Key.PARAMS,
+ Key.SHARED_RAND_PREVIOUS_VALUE, Key.SHARED_RAND_CURRENT_VALUE,
+ Key.DIRECTORY_FOOTER, Key.BANDWIDTH_WEIGHTS);
+ this.checkAtMostOnceKeys(atMostOnceKeys);
+ this.checkFirstKey(Key.NETWORK_STATUS_VERSION);
+ this.clearParsedKeys();
this.calculateDigest();
}
private void calculateDigest() throws DescriptorParseException {
try {
String ascii = new String(this.getRawDescriptorBytes(), "US-ASCII");
- String startToken = "network-status-version ";
- String sigToken = "\ndirectory-signature ";
+ String startToken = Key.NETWORK_STATUS_VERSION.keyword + SP;
+ String sigToken = NL + Key.DIRECTORY_SIGNATURE.keyword + SP;
if (!ascii.contains(sigToken)) {
return;
}
@@ -94,64 +94,64 @@ public class RelayNetworkStatusConsensusImpl extends NetworkStatusImpl
protected void parseHeader(byte[] headerBytes)
throws DescriptorParseException {
- Scanner scanner = new Scanner(new String(headerBytes)).useDelimiter("\n");
+ Scanner scanner = new Scanner(new String(headerBytes)).useDelimiter(NL);
while (scanner.hasNext()) {
String line = scanner.next();
String[] parts = line.split("[ \t]+");
- String keyword = parts[0];
- switch (keyword) {
- case "network-status-version":
+ Key key = Key.get(parts[0]);
+ switch (key) {
+ case NETWORK_STATUS_VERSION:
this.parseNetworkStatusVersionLine(line, parts);
break;
- case "vote-status":
+ case VOTE_STATUS:
this.parseVoteStatusLine(line, parts);
break;
- case "consensus-method":
+ case CONSENSUS_METHOD:
this.parseConsensusMethodLine(line, parts);
break;
- case "valid-after":
+ case VALID_AFTER:
this.parseValidAfterLine(line, parts);
break;
- case "fresh-until":
+ case FRESH_UNTIL:
this.parseFreshUntilLine(line, parts);
break;
- case "valid-until":
+ case VALID_UNTIL:
this.parseValidUntilLine(line, parts);
break;
- case "voting-delay":
+ case VOTING_DELAY:
this.parseVotingDelayLine(line, parts);
break;
- case "client-versions":
+ case CLIENT_VERSIONS:
this.parseClientVersionsLine(line, parts);
break;
- case "server-versions":
+ case SERVER_VERSIONS:
this.parseServerVersionsLine(line, parts);
break;
- case "recommended-client-protocols":
+ case RECOMMENDED_CLIENT_PROTOCOLS:
this.parseRecommendedClientProtocolsLine(line, parts);
break;
- case "recommended-relay-protocols":
+ case RECOMMENDED_RELAY_PROTOCOLS:
this.parseRecommendedRelayProtocolsLine(line, parts);
break;
- case "required-client-protocols":
+ case REQUIRED_CLIENT_PROTOCOLS:
this.parseRequiredClientProtocolsLine(line, parts);
break;
- case "required-relay-protocols":
+ case REQUIRED_RELAY_PROTOCOLS:
this.parseRequiredRelayProtocolsLine(line, parts);
break;
- case "package":
+ case PACKAGE:
this.parsePackageLine(line, parts);
break;
- case "known-flags":
+ case KNOWN_FLAGS:
this.parseKnownFlagsLine(line, parts);
break;
- case "params":
+ case PARAMS:
this.parseParamsLine(line, parts);
break;
- case "shared-rand-previous-value":
+ case SHARED_RAND_PREVIOUS_VALUE:
this.parseSharedRandPreviousValueLine(line, parts);
break;
- case "shared-rand-current-value":
+ case SHARED_RAND_CURRENT_VALUE:
this.parseSharedRandCurrentValueLine(line, parts);
break;
default:
@@ -188,15 +188,15 @@ public class RelayNetworkStatusConsensusImpl extends NetworkStatusImpl
protected void parseFooter(byte[] footerBytes)
throws DescriptorParseException {
- Scanner scanner = new Scanner(new String(footerBytes)).useDelimiter("\n");
+ Scanner scanner = new Scanner(new String(footerBytes)).useDelimiter(NL);
while (scanner.hasNext()) {
String line = scanner.next();
String[] parts = line.split("[ \t]+");
- String keyword = parts[0];
- switch (keyword) {
- case "directory-footer":
+ Key key = Key.get(parts[0]);
+ switch (key) {
+ case DIRECTORY_FOOTER:
break;
- case "bandwidth-weights":
+ case BANDWIDTH_WEIGHTS:
this.parseBandwidthWeightsLine(line, parts);
break;
default:
@@ -215,7 +215,7 @@ public class RelayNetworkStatusConsensusImpl extends NetworkStatusImpl
private void parseNetworkStatusVersionLine(String line, String[] parts)
throws DescriptorParseException {
- if (!line.startsWith("network-status-version 3")) {
+ if (!line.startsWith(Key.NETWORK_STATUS_VERSION.keyword + SP + "3")) {
throw new DescriptorParseException("Illegal network status version "
+ "number in line '" + line + "'.");
}
@@ -335,7 +335,7 @@ public class RelayNetworkStatusConsensusImpl extends NetworkStatusImpl
if (this.packageLines == null) {
this.packageLines = new ArrayList<>();
}
- this.packageLines.add(line.substring("package ".length()));
+ this.packageLines.add(line.substring(Key.PACKAGE.keyword.length() + 1));
}
private void parseKnownFlagsLine(String line, String[] parts)
diff --git a/src/main/java/org/torproject/descriptor/impl/RelayNetworkStatusImpl.java b/src/main/java/org/torproject/descriptor/impl/RelayNetworkStatusImpl.java
index 143540c..121cdc9 100644
--- a/src/main/java/org/torproject/descriptor/impl/RelayNetworkStatusImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/RelayNetworkStatusImpl.java
@@ -11,7 +11,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashSet;
+import java.util.EnumSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
@@ -42,29 +42,29 @@ public class RelayNetworkStatusImpl extends NetworkStatusImpl
boolean failUnrecognizedDescriptorLines)
throws DescriptorParseException {
super(statusBytes, failUnrecognizedDescriptorLines, false, true);
- Set<String> exactlyOnceKeywords = new HashSet<>(Arrays.asList((
- "network-status-version,dir-source,fingerprint,contact,"
- + "dir-signing-key,published").split(",")));
- this.checkExactlyOnceKeywords(exactlyOnceKeywords);
- Set<String> atMostOnceKeywords = new HashSet<>(Arrays.asList(
- "dir-options,client-versions,server-versions".split(",")));
- this.checkAtMostOnceKeywords(atMostOnceKeywords);
- this.checkFirstKeyword("network-status-version");
- this.clearParsedKeywords();
+ Set<Key> exactlyOnceKeys = EnumSet.of(
+ Key.NETWORK_STATUS_VERSION, Key.DIR_SOURCE, Key.FINGERPRINT,
+ Key.CONTACT, Key.DIR_SIGNING_KEY, Key.PUBLISHED);
+ this.checkExactlyOnceKeys(exactlyOnceKeys);
+ Set<Key> atMostOnceKeys = EnumSet.of(
+ Key.DIR_OPTIONS, Key.CLIENT_VERSIONS, Key.SERVER_VERSIONS);
+ this.checkAtMostOnceKeys(atMostOnceKeys);
+ this.checkFirstKey(Key.NETWORK_STATUS_VERSION);
+ this.clearParsedKeys();
this.calculateDigest();
}
private void calculateDigest() throws DescriptorParseException {
try {
String ascii = new String(this.getRawDescriptorBytes(), "US-ASCII");
- String startToken = "network-status-version ";
- String sigToken = "\ndirectory-signature ";
+ String startToken = Key.NETWORK_STATUS_VERSION.keyword + SP;
+ String sigToken = NL + Key.DIRECTORY_SIGNATURE.keyword + SP;
if (!ascii.contains(sigToken)) {
return;
}
int start = ascii.indexOf(startToken);
int sig = ascii.indexOf(sigToken) + sigToken.length();
- sig = ascii.indexOf("\n", sig) + 1;
+ sig = ascii.indexOf(NL, sig) + 1;
if (start >= 0 && sig >= 0 && sig > start) {
byte[] forDigest = new byte[sig - start];
System.arraycopy(this.getRawDescriptorBytes(), start,
@@ -86,8 +86,8 @@ public class RelayNetworkStatusImpl extends NetworkStatusImpl
protected void parseHeader(byte[] headerBytes)
throws DescriptorParseException {
- Scanner scanner = new Scanner(new String(headerBytes)).useDelimiter("\n");
- String nextCrypto = "";
+ Scanner scanner = new Scanner(new String(headerBytes)).useDelimiter(NL);
+ Key nextCrypto = Key.EMPTY;
StringBuilder crypto = null;
while (scanner.hasNext()) {
String line = scanner.next();
@@ -95,55 +95,55 @@ public class RelayNetworkStatusImpl extends NetworkStatusImpl
continue;
}
String[] parts = line.split("[ \t]+");
- String keyword = parts[0];
- switch (keyword) {
- case "network-status-version":
+ Key key = Key.get(parts[0]);
+ switch (key) {
+ case NETWORK_STATUS_VERSION:
this.parseNetworkStatusVersionLine(line, parts);
break;
- case "dir-source":
+ case DIR_SOURCE:
this.parseDirSourceLine(line, parts);
break;
- case "fingerprint":
+ case FINGERPRINT:
this.parseFingerprintLine(line, parts);
break;
- case "contact":
+ case CONTACT:
this.parseContactLine(line, parts);
break;
- case "dir-signing-key":
+ case DIR_SIGNING_KEY:
this.parseDirSigningKeyLine(line, parts);
- nextCrypto = "dir-signing-key";
+ nextCrypto = key;
break;
- case "client-versions":
+ case CLIENT_VERSIONS:
this.parseClientVersionsLine(line, parts);
break;
- case "server-versions":
+ case SERVER_VERSIONS:
this.parseServerVersionsLine(line, parts);
break;
- case "published":
+ case PUBLISHED:
this.parsePublishedLine(line, parts);
break;
- case "dir-options":
+ case DIR_OPTIONS:
this.parseDirOptionsLine(line, parts);
break;
- case "-----BEGIN":
+ case CRYPTO_BEGIN:
crypto = new StringBuilder();
- crypto.append(line).append("\n");
+ crypto.append(line).append(NL);
break;
- case "-----END":
- crypto.append(line).append("\n");
+ case CRYPTO_END:
+ crypto.append(line).append(NL);
String cryptoString = crypto.toString();
crypto = null;
- if (nextCrypto.equals("dir-signing-key")) {
+ if (nextCrypto.equals(Key.DIR_SIGNING_KEY)) {
this.dirSigningKey = cryptoString;
} else {
throw new DescriptorParseException("Unrecognized crypto "
+ "block in v2 network status.");
}
- nextCrypto = "";
+ nextCrypto = Key.EMPTY;
break;
default:
if (crypto != null) {
- crypto.append(line).append("\n");
+ crypto.append(line).append(NL);
} else if (this.failUnrecognizedDescriptorLines) {
throw new DescriptorParseException("Unrecognized line '"
+ line + "' in v2 network status.");
@@ -166,37 +166,37 @@ public class RelayNetworkStatusImpl extends NetworkStatusImpl
protected void parseDirectorySignature(byte[] directorySignatureBytes)
throws DescriptorParseException {
Scanner scanner = new Scanner(new String(directorySignatureBytes))
- .useDelimiter("\n");
- String nextCrypto = "";
+ .useDelimiter(NL);
+ Key nextCrypto = Key.EMPTY;
StringBuilder crypto = null;
while (scanner.hasNext()) {
String line = scanner.next();
String[] parts = line.split("[ \t]+");
- String keyword = parts[0];
- switch (keyword) {
- case "directory-signature":
+ Key key = Key.get(parts[0]);
+ switch (key) {
+ case DIRECTORY_SIGNATURE:
this.parseDirectorySignatureLine(line, parts);
- nextCrypto = "directory-signature";
+ nextCrypto = key;
break;
- case "-----BEGIN":
+ case CRYPTO_BEGIN:
crypto = new StringBuilder();
- crypto.append(line).append("\n");
+ crypto.append(line).append(NL);
break;
- case "-----END":
- crypto.append(line).append("\n");
+ case CRYPTO_END:
+ crypto.append(line).append(NL);
String cryptoString = crypto.toString();
crypto = null;
- if (nextCrypto.equals("directory-signature")) {
+ if (nextCrypto.equals(Key.DIRECTORY_SIGNATURE)) {
this.directorySignature = cryptoString;
} else {
throw new DescriptorParseException("Unrecognized crypto "
+ "block in v2 network status.");
}
- nextCrypto = "";
+ nextCrypto = Key.EMPTY;
break;
default:
if (crypto != null) {
- crypto.append(line).append("\n");
+ crypto.append(line).append(NL);
} else if (this.failUnrecognizedDescriptorLines) {
throw new DescriptorParseException("Unrecognized line '"
+ line + "' in v2 network status.");
@@ -212,7 +212,7 @@ public class RelayNetworkStatusImpl extends NetworkStatusImpl
private void parseNetworkStatusVersionLine(String line, String[] parts)
throws DescriptorParseException {
- if (!line.equals("network-status-version 2")) {
+ if (!line.equals(Key.NETWORK_STATUS_VERSION.keyword + SP + "2")) {
throw new DescriptorParseException("Illegal network status version "
+ "number in line '" + line + "'.");
}
@@ -246,8 +246,8 @@ public class RelayNetworkStatusImpl extends NetworkStatusImpl
private void parseContactLine(String line, String[] parts)
throws DescriptorParseException {
- if (line.length() > "contact ".length()) {
- this.contactLine = line.substring("contact ".length());
+ if (line.length() > Key.CONTACT.keyword.length() + 1) {
+ this.contactLine = line.substring(Key.CONTACT.keyword.length() + 1);
} else {
this.contactLine = "";
}
@@ -255,7 +255,7 @@ public class RelayNetworkStatusImpl extends NetworkStatusImpl
private void parseDirSigningKeyLine(String line, String[] parts)
throws DescriptorParseException {
- if (!line.equals("dir-signing-key")) {
+ if (!line.equals(Key.DIR_SIGNING_KEY.keyword)) {
throw new DescriptorParseException("Illegal line '" + line + "'.");
}
}
diff --git a/src/main/java/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java b/src/main/java/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
index 05f5cc2..c645928 100644
--- a/src/main/java/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
@@ -12,7 +12,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashSet;
+import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
@@ -33,7 +33,7 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
List<RelayNetworkStatusVote> parsedVotes = new ArrayList<>();
List<byte[]> splitVotesBytes =
DescriptorImpl.splitRawDescriptorBytes(votesBytes,
- "network-status-version 3");
+ Key.NETWORK_STATUS_VERSION.keyword + SP + "3");
for (byte[] voteBytes : splitVotesBytes) {
RelayNetworkStatusVote parsedVote =
new RelayNetworkStatusVoteImpl(voteBytes,
@@ -47,27 +47,25 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
boolean failUnrecognizedDescriptorLines)
throws DescriptorParseException {
super(voteBytes, failUnrecognizedDescriptorLines, false, false);
- Set<String> exactlyOnceKeywords = new HashSet<>(Arrays.asList((
- "vote-status,published,valid-after,fresh-until,"
- + "valid-until,voting-delay,known-flags,dir-source,"
- + "dir-key-certificate-version,fingerprint,dir-key-published,"
- + "dir-key-expires,dir-identity-key,dir-signing-key,"
- + "dir-key-certification").split(",")));
- this.checkExactlyOnceKeywords(exactlyOnceKeywords);
- Set<String> atMostOnceKeywords = new HashSet<>(Arrays.asList((
- "consensus-methods,client-versions,server-versions,"
- + "recommended-client-protocols,recommended-relay-protocols,"
- + "required-client-protocols,required-relay-protocols,"
- + "flag-thresholds,params,contact,shared-rand-participate,"
- + "shared-rand-previous-value,shared-rand-current-value,"
- + "legacy-key,dir-key-crosscert,dir-address,directory-footer")
- .split(",")));
- this.checkAtMostOnceKeywords(atMostOnceKeywords);
- Set<String> atLeastOnceKeywords = new HashSet<>(Arrays.asList(
- "directory-signature"));
- this.checkAtLeastOnceKeywords(atLeastOnceKeywords);
- this.checkFirstKeyword("network-status-version");
- this.clearParsedKeywords();
+ Set<Key> exactlyOnceKeys = EnumSet.of(
+ Key.VOTE_STATUS, Key.PUBLISHED, Key.VALID_AFTER, Key.FRESH_UNTIL,
+ Key.VALID_UNTIL, Key.VOTING_DELAY, Key.KNOWN_FLAGS, Key.DIR_SOURCE,
+ Key.DIR_KEY_CERTIFICATE_VERSION, Key.FINGERPRINT, Key.DIR_KEY_PUBLISHED,
+ Key.DIR_KEY_EXPIRES, Key.DIR_IDENTITY_KEY, Key.DIR_SIGNING_KEY,
+ Key.DIR_KEY_CERTIFICATION);
+ this.checkExactlyOnceKeys(exactlyOnceKeys);
+ Set<Key> atMostOnceKeys = EnumSet.of(
+ Key.CONSENSUS_METHODS, Key.CLIENT_VERSIONS, Key.SERVER_VERSIONS,
+ Key.RECOMMENDED_CLIENT_PROTOCOLS, Key.RECOMMENDED_RELAY_PROTOCOLS,
+ Key.REQUIRED_CLIENT_PROTOCOLS, Key.REQUIRED_RELAY_PROTOCOLS,
+ Key.FLAG_THRESHOLDS, Key.PARAMS, Key.CONTACT,
+ Key.SHARED_RAND_PARTICIPATE, Key.SHARED_RAND_PREVIOUS_VALUE,
+ Key.SHARED_RAND_CURRENT_VALUE, Key.LEGACY_KEY, Key.DIR_KEY_CROSSCERT,
+ Key.DIR_ADDRESS, Key.DIRECTORY_FOOTER);
+ this.checkAtMostOnceKeys(atMostOnceKeys);
+ this.checkAtLeastOnceKeys(EnumSet.of(Key.DIRECTORY_SIGNATURE));
+ this.checkFirstKey(Key.NETWORK_STATUS_VERSION);
+ this.clearParsedKeys();
this.calculateDigest();
}
@@ -116,150 +114,150 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
this.enoughMtbfInfo = -1;
this.ignoringAdvertisedBws = -1;
- Scanner scanner = new Scanner(new String(headerBytes)).useDelimiter("\n");
- String nextCrypto = "";
+ Scanner scanner = new Scanner(new String(headerBytes)).useDelimiter(NL);
+ Key nextCrypto = Key.EMPTY;
StringBuilder crypto = null;
while (scanner.hasNext()) {
String line = scanner.next();
String[] parts = line.split("[ \t]+");
- String keyword = parts[0];
- switch (keyword) {
- case "network-status-version":
+ Key key = Key.get(parts[0]);
+ switch (key) {
+ case NETWORK_STATUS_VERSION:
this.parseNetworkStatusVersionLine(line, parts);
break;
- case "vote-status":
+ case VOTE_STATUS:
this.parseVoteStatusLine(line, parts);
break;
- case "consensus-methods":
+ case CONSENSUS_METHODS:
this.parseConsensusMethodsLine(line, parts);
break;
- case "published":
+ case PUBLISHED:
this.parsePublishedLine(line, parts);
break;
- case "valid-after":
+ case VALID_AFTER:
this.parseValidAfterLine(line, parts);
break;
- case "fresh-until":
+ case FRESH_UNTIL:
this.parseFreshUntilLine(line, parts);
break;
- case "valid-until":
+ case VALID_UNTIL:
this.parseValidUntilLine(line, parts);
break;
- case "voting-delay":
+ case VOTING_DELAY:
this.parseVotingDelayLine(line, parts);
break;
- case "client-versions":
+ case CLIENT_VERSIONS:
this.parseClientVersionsLine(line, parts);
break;
- case "server-versions":
+ case SERVER_VERSIONS:
this.parseServerVersionsLine(line, parts);
break;
- case "recommended-client-protocols":
+ case RECOMMENDED_CLIENT_PROTOCOLS:
this.parseRecommendedClientProtocolsLine(line, parts);
break;
- case "recommended-relay-protocols":
+ case RECOMMENDED_RELAY_PROTOCOLS:
this.parseRecommendedRelayProtocolsLine(line, parts);
break;
- case "required-client-protocols":
+ case REQUIRED_CLIENT_PROTOCOLS:
this.parseRequiredClientProtocolsLine(line, parts);
break;
- case "required-relay-protocols":
+ case REQUIRED_RELAY_PROTOCOLS:
this.parseRequiredRelayProtocolsLine(line, parts);
break;
- case "package":
+ case PACKAGE:
this.parsePackageLine(line, parts);
break;
- case "known-flags":
+ case KNOWN_FLAGS:
this.parseKnownFlagsLine(line, parts);
break;
- case "flag-thresholds":
+ case FLAG_THRESHOLDS:
this.parseFlagThresholdsLine(line, parts);
break;
- case "params":
+ case PARAMS:
this.parseParamsLine(line, parts);
break;
- case "dir-source":
+ case DIR_SOURCE:
this.parseDirSourceLine(line, parts);
break;
- case "contact":
+ case CONTACT:
this.parseContactLine(line, parts);
break;
- case "shared-rand-participate":
+ case SHARED_RAND_PARTICIPATE:
this.parseSharedRandParticipateLine(line, parts);
break;
- case "shared-rand-commit":
+ case SHARED_RAND_COMMIT:
this.parseSharedRandCommitLine(line, parts);
break;
- case "shared-rand-previous-value":
+ case SHARED_RAND_PREVIOUS_VALUE:
this.parseSharedRandPreviousValueLine(line, parts);
break;
- case "shared-rand-current-value":
+ case SHARED_RAND_CURRENT_VALUE:
this.parseSharedRandCurrentValueLine(line, parts);
break;
- case "dir-key-certificate-version":
+ case DIR_KEY_CERTIFICATE_VERSION:
this.parseDirKeyCertificateVersionLine(line, parts);
break;
- case "dir-address":
+ case DIR_ADDRESS:
this.parseDirAddressLine(line, parts);
break;
- case "fingerprint":
+ case FINGERPRINT:
this.parseFingerprintLine(line, parts);
break;
- case "legacy-dir-key":
+ case LEGACY_DIR_KEY:
this.parseLegacyDirKeyLine(line, parts);
break;
- case "dir-key-published":
+ case DIR_KEY_PUBLISHED:
this.parseDirKeyPublished(line, parts);
break;
- case "dir-key-expires":
+ case DIR_KEY_EXPIRES:
this.parseDirKeyExpiresLine(line, parts);
break;
- case "dir-identity-key":
+ case DIR_IDENTITY_KEY:
this.parseDirIdentityKeyLine(line, parts);
- nextCrypto = "dir-identity-key";
+ nextCrypto = key;
break;
- case "dir-signing-key":
+ case DIR_SIGNING_KEY:
this.parseDirSigningKeyLine(line, parts);
- nextCrypto = "dir-signing-key";
+ nextCrypto = key;
break;
- case "dir-key-crosscert":
+ case DIR_KEY_CROSSCERT:
this.parseDirKeyCrosscertLine(line, parts);
- nextCrypto = "dir-key-crosscert";
+ nextCrypto = key;
break;
- case "dir-key-certification":
+ case DIR_KEY_CERTIFICATION:
this.parseDirKeyCertificationLine(line, parts);
- nextCrypto = "dir-key-certification";
+ nextCrypto = key;
break;
- case "-----BEGIN":
+ case CRYPTO_BEGIN:
crypto = new StringBuilder();
- crypto.append(line).append("\n");
+ crypto.append(line).append(NL);
break;
- case "-----END":
- crypto.append(line).append("\n");
+ case CRYPTO_END:
+ crypto.append(line).append(NL);
String cryptoString = crypto.toString();
crypto = null;
switch (nextCrypto) {
- case "dir-identity-key":
+ case DIR_IDENTITY_KEY:
this.dirIdentityKey = cryptoString;
break;
- case "dir-signing-key":
+ case DIR_SIGNING_KEY:
this.dirSigningKey = cryptoString;
break;
- case "dir-key-crosscert":
+ case DIR_KEY_CROSSCERT:
this.dirKeyCrosscert = cryptoString;
break;
- case "dir-key-certification":
+ case DIR_KEY_CERTIFICATION:
this.dirKeyCertification = cryptoString;
break;
default:
throw new DescriptorParseException("Unrecognized crypto "
+ "block in vote.");
}
- nextCrypto = "";
+ nextCrypto = Key.EMPTY;
break;
default:
if (crypto != null) {
- crypto.append(line).append("\n");
+ crypto.append(line).append(NL);
} else {
if (this.failUnrecognizedDescriptorLines) {
throw new DescriptorParseException("Unrecognized line '"
@@ -277,7 +275,7 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
private void parseNetworkStatusVersionLine(String line, String[] parts)
throws DescriptorParseException {
- if (!line.equals("network-status-version 3")) {
+ if (!line.equals(Key.NETWORK_STATUS_VERSION.keyword + SP + "3")) {
throw new DescriptorParseException("Illegal network status version "
+ "number in line '" + line + "'.");
}
@@ -399,7 +397,7 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
if (this.packageLines == null) {
this.packageLines = new ArrayList<>();
}
- this.packageLines.add(line.substring("package ".length()));
+ this.packageLines.add(line.substring(Key.PACKAGE.keyword.length() + 1));
}
private void parseKnownFlagsLine(String line, String[] parts)
@@ -492,8 +490,8 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
private void parseContactLine(String line, String[] parts)
throws DescriptorParseException {
- if (line.length() > "contact ".length()) {
- this.contactLine = line.substring("contact ".length());
+ if (line.length() > Key.CONTACT.keyword.length() + 1) {
+ this.contactLine = line.substring(Key.CONTACT.keyword.length() + 1);
} else {
this.contactLine = "";
}
@@ -604,38 +602,38 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
private void parseDirIdentityKeyLine(String line, String[] parts)
throws DescriptorParseException {
- if (!line.equals("dir-identity-key")) {
+ if (!line.equals(Key.DIR_IDENTITY_KEY.keyword)) {
throw new DescriptorParseException("Illegal line '" + line + "'.");
}
}
private void parseDirSigningKeyLine(String line, String[] parts)
throws DescriptorParseException {
- if (!line.equals("dir-signing-key")) {
+ if (!line.equals(Key.DIR_SIGNING_KEY.keyword)) {
throw new DescriptorParseException("Illegal line '" + line + "'.");
}
}
private void parseDirKeyCrosscertLine(String line, String[] parts)
throws DescriptorParseException {
- if (!line.equals("dir-key-crosscert")) {
+ if (!line.equals(Key.DIR_KEY_CROSSCERT.keyword)) {
throw new DescriptorParseException("Illegal line '" + line + "'.");
}
}
private void parseDirKeyCertificationLine(String line, String[] parts)
throws DescriptorParseException {
- if (!line.equals("dir-key-certification")) {
+ if (!line.equals(Key.DIR_KEY_CERTIFICATION.keyword)) {
throw new DescriptorParseException("Illegal line '" + line + "'.");
}
}
protected void parseFooter(byte[] footerBytes)
throws DescriptorParseException {
- Scanner scanner = new Scanner(new String(footerBytes)).useDelimiter("\n");
+ Scanner scanner = new Scanner(new String(footerBytes)).useDelimiter(NL);
while (scanner.hasNext()) {
String line = scanner.next();
- if (!line.equals("directory-footer")) {
+ if (!line.equals(Key.DIRECTORY_FOOTER.keyword)) {
if (this.failUnrecognizedDescriptorLines) {
throw new DescriptorParseException("Unrecognized line '"
+ line + "' in vote.");
diff --git a/src/main/java/org/torproject/descriptor/impl/RelayServerDescriptorImpl.java b/src/main/java/org/torproject/descriptor/impl/RelayServerDescriptorImpl.java
index 3353ec1..eefa24f 100644
--- a/src/main/java/org/torproject/descriptor/impl/RelayServerDescriptorImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/RelayServerDescriptorImpl.java
@@ -19,7 +19,7 @@ public class RelayServerDescriptorImpl extends ServerDescriptorImpl
List<ServerDescriptor> parsedDescriptors = new ArrayList<>();
List<byte[]> splitDescriptorsBytes =
DescriptorImpl.splitRawDescriptorBytes(descriptorsBytes,
- "router ");
+ Key.ROUTER.keyword + SP);
for (byte[] descriptorBytes : splitDescriptorsBytes) {
ServerDescriptor parsedDescriptor =
new RelayServerDescriptorImpl(descriptorBytes,
diff --git a/src/main/java/org/torproject/descriptor/impl/ServerDescriptorImpl.java b/src/main/java/org/torproject/descriptor/impl/ServerDescriptorImpl.java
index ac113d2..70bd42c 100644
--- a/src/main/java/org/torproject/descriptor/impl/ServerDescriptorImpl.java
+++ b/src/main/java/org/torproject/descriptor/impl/ServerDescriptorImpl.java
@@ -12,7 +12,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashSet;
+import java.util.EnumSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
@@ -25,6 +25,20 @@ import javax.xml.bind.DatatypeConverter;
public abstract class ServerDescriptorImpl extends DescriptorImpl
implements ServerDescriptor {
+ private static final Set<Key> atMostOnce = EnumSet.of(
+ Key.IDENTITY_ED25519, Key.MASTER_KEY_ED25519, Key.PLATFORM, Key.PROTO,
+ Key.FINGERPRINT, Key.HIBERNATING, Key.UPTIME, Key.CONTACT, Key.FAMILY,
+ Key.READ_HISTORY, Key.WRITE_HISTORY, Key.EVENTDNS, Key.CACHES_EXTRA_INFO,
+ Key.EXTRA_INFO_DIGEST, Key.HIDDEN_SERVICE_DIR, Key.PROTOCOLS,
+ Key.ALLOW_SINGLE_HOP_EXITS, Key.ONION_KEY, Key.SIGNING_KEY,
+ Key.IPV6_POLICY, Key.NTOR_ONION_KEY, Key.ONION_KEY_CROSSCERT,
+ Key.NTOR_ONION_KEY_CROSSCERT, Key.TUNNELLED_DIR_SERVER,
+ Key.ROUTER_SIG_ED25519, Key.ROUTER_SIGNATURE, Key.ROUTER_DIGEST_SHA256,
+ Key.ROUTER_DIGEST);
+
+ private static final Set<Key> exactlyOnce = EnumSet.of(
+ Key.ROUTER, Key.BANDWIDTH, Key.PUBLISHED);
+
protected ServerDescriptorImpl(byte[] descriptorBytes,
boolean failUnrecognizedDescriptorLines)
throws DescriptorParseException {
@@ -32,184 +46,173 @@ public abstract class ServerDescriptorImpl extends DescriptorImpl
this.parseDescriptorBytes();
this.calculateDigest();
this.calculateDigestSha256();
- Set<String> exactlyOnceKeywords = new HashSet<>(Arrays.asList(
- "router,bandwidth,published".split(",")));
- this.checkExactlyOnceKeywords(exactlyOnceKeywords);
- Set<String> atMostOnceKeywords = new HashSet<>(Arrays.asList((
- "identity-ed25519,master-key-ed25519,platform,proto,fingerprint,"
- + "hibernating,uptime,contact,family,read-history,write-history,"
- + "eventdns,caches-extra-info,extra-info-digest,"
- + "hidden-service-dir,protocols,allow-single-hop-exits,onion-key,"
- + "signing-key,ipv6-policy,ntor-onion-key,onion-key-crosscert,"
- + "ntor-onion-key-crosscert,tunnelled-dir-server,"
- + "router-sig-ed25519,router-signature,router-digest-sha256,"
- + "router-digest").split(",")));
- this.checkAtMostOnceKeywords(atMostOnceKeywords);
- this.checkFirstKeyword("router");
- if (this.getKeywordCount("accept") == 0
- && this.getKeywordCount("reject") == 0) {
+ this.checkExactlyOnceKeys(exactlyOnce);
+ this.checkAtMostOnceKeys(atMostOnce);
+ this.checkFirstKey(Key.ROUTER);
+ if (this.getKeyCount(Key.ACCEPT) == 0
+ && this.getKeyCount(Key.REJECT) == 0) {
throw new DescriptorParseException("Either keyword 'accept' or "
+ "'reject' must be contained at least once.");
}
- this.clearParsedKeywords();
+ this.clearParsedKeys();
return;
}
private void parseDescriptorBytes() throws DescriptorParseException {
Scanner scanner = new Scanner(new String(this.rawDescriptorBytes))
- .useDelimiter("\n");
- String nextCrypto = "";
+ .useDelimiter(NL);
+ Key nextCrypto = Key.EMPTY;
List<String> cryptoLines = null;
while (scanner.hasNext()) {
String line = scanner.next();
if (line.startsWith("@")) {
continue;
}
- String lineNoOpt = line.startsWith("opt ")
- ? line.substring("opt ".length()) : line;
+ String lineNoOpt = line.startsWith(Key.OPT.keyword + SP)
+ ? line.substring(Key.OPT.keyword.length() + 1) : line;
String[] partsNoOpt = lineNoOpt.split("[ \t]+");
- String keyword = partsNoOpt[0];
- switch (keyword) {
- case "router":
+ Key key = Key.get(partsNoOpt[0]);
+ switch (key) {
+ case ROUTER:
this.parseRouterLine(line, lineNoOpt, partsNoOpt);
break;
- case "or-address":
+ case OR_ADDRESS:
this.parseOrAddressLine(line, lineNoOpt, partsNoOpt);
break;
- case "bandwidth":
+ case BANDWIDTH:
this.parseBandwidthLine(line, lineNoOpt, partsNoOpt);
break;
- case "platform":
+ case PLATFORM:
this.parsePlatformLine(line, lineNoOpt, partsNoOpt);
break;
- case "proto":
+ case PROTO:
this.parseProtoLine(line, lineNoOpt, partsNoOpt);
break;
- case "published":
+ case PUBLISHED:
this.parsePublishedLine(line, lineNoOpt, partsNoOpt);
break;
- case "fingerprint":
+ case FINGERPRINT:
this.parseFingerprintLine(line, lineNoOpt, partsNoOpt);
break;
- case "hibernating":
+ case HIBERNATING:
this.parseHibernatingLine(line, lineNoOpt, partsNoOpt);
break;
- case "uptime":
+ case UPTIME:
this.parseUptimeLine(line, lineNoOpt, partsNoOpt);
break;
- case "onion-key":
+ case ONION_KEY:
this.parseOnionKeyLine(line, lineNoOpt, partsNoOpt);
- nextCrypto = "onion-key";
+ nextCrypto = key;
break;
- case "signing-key":
+ case SIGNING_KEY:
this.parseSigningKeyLine(line, lineNoOpt, partsNoOpt);
- nextCrypto = "signing-key";
+ nextCrypto = key;
break;
- case "accept":
+ case ACCEPT:
this.parseAcceptLine(line, lineNoOpt, partsNoOpt);
break;
- case "reject":
+ case REJECT:
this.parseRejectLine(line, lineNoOpt, partsNoOpt);
break;
- case "router-signature":
+ case ROUTER_SIGNATURE:
this.parseRouterSignatureLine(line, lineNoOpt, partsNoOpt);
- nextCrypto = "router-signature";
+ nextCrypto = key;
break;
- case "contact":
+ case CONTACT:
this.parseContactLine(line, lineNoOpt, partsNoOpt);
break;
- case "family":
+ case FAMILY:
this.parseFamilyLine(line, lineNoOpt, partsNoOpt);
break;
- case "read-history":
+ case READ_HISTORY:
this.parseReadHistoryLine(line, lineNoOpt, partsNoOpt);
break;
- case "write-history":
+ case WRITE_HISTORY:
this.parseWriteHistoryLine(line, lineNoOpt, partsNoOpt);
break;
- case "eventdns":
+ case EVENTDNS:
this.parseEventdnsLine(line, lineNoOpt, partsNoOpt);
break;
- case "caches-extra-info":
+ case CACHES_EXTRA_INFO:
this.parseCachesExtraInfoLine(line, lineNoOpt, partsNoOpt);
break;
- case "extra-info-digest":
+ case EXTRA_INFO_DIGEST:
this.parseExtraInfoDigestLine(line, lineNoOpt, partsNoOpt);
break;
- case "hidden-service-dir":
+ case HIDDEN_SERVICE_DIR:
this.parseHiddenServiceDirLine(line, lineNoOpt, partsNoOpt);
break;
- case "protocols":
+ case PROTOCOLS:
this.parseProtocolsLine(line, lineNoOpt, partsNoOpt);
break;
- case "allow-single-hop-exits":
+ case ALLOW_SINGLE_HOP_EXITS:
this.parseAllowSingleHopExitsLine(line, lineNoOpt, partsNoOpt);
break;
- case "dircacheport":
+ case DIRCACHEPORT:
this.parseDircacheportLine(line, lineNoOpt, partsNoOpt);
break;
- case "router-digest":
+ case ROUTER_DIGEST:
this.parseRouterDigestLine(line, lineNoOpt, partsNoOpt);
break;
- case "router-digest-sha256":
+ case ROUTER_DIGEST_SHA256:
this.parseRouterDigestSha256Line(line, lineNoOpt, partsNoOpt);
break;
- case "ipv6-policy":
+ case IPV6_POLICY:
this.parseIpv6PolicyLine(line, lineNoOpt, partsNoOpt);
break;
- case "ntor-onion-key":
+ case NTOR_ONION_KEY:
this.parseNtorOnionKeyLine(line, lineNoOpt, partsNoOpt);
break;
- case "identity-ed25519":
+ case IDENTITY_ED25519:
this.parseIdentityEd25519Line(line, lineNoOpt, partsNoOpt);
- nextCrypto = "identity-ed25519";
+ nextCrypto = key;
break;
- case "master-key-ed25519":
+ case MASTER_KEY_ED25519:
this.parseMasterKeyEd25519Line(line, lineNoOpt, partsNoOpt);
break;
- case "router-sig-ed25519":
+ case ROUTER_SIG_ED25519:
this.parseRouterSigEd25519Line(line, lineNoOpt, partsNoOpt);
break;
- case "onion-key-crosscert":
+ case ONION_KEY_CROSSCERT:
this.parseOnionKeyCrosscert(line, lineNoOpt, partsNoOpt);
- nextCrypto = "onion-key-crosscert";
+ nextCrypto = key;
break;
- case "ntor-onion-key-crosscert":
+ case NTOR_ONION_KEY_CROSSCERT:
this.parseNtorOnionKeyCrosscert(line, lineNoOpt, partsNoOpt);
- nextCrypto = "ntor-onion-key-crosscert";
+ nextCrypto = key;
break;
- case "tunnelled-dir-server":
+ case TUNNELLED_DIR_SERVER:
this.parseTunnelledDirServerLine(line, lineNoOpt, partsNoOpt);
break;
- case "-----BEGIN":
+ case CRYPTO_BEGIN:
cryptoLines = new ArrayList<>();
cryptoLines.add(line);
break;
- case "-----END":
+ case CRYPTO_END:
cryptoLines.add(line);
StringBuilder sb = new StringBuilder();
for (String cryptoLine : cryptoLines) {
- sb.append("\n").append(cryptoLine);
+ sb.append(NL).append(cryptoLine);
}
String cryptoString = sb.toString().substring(1);
switch (nextCrypto) {
- case "onion-key":
+ case ONION_KEY:
this.onionKey = cryptoString;
break;
- case "signing-key":
+ case SIGNING_KEY:
this.signingKey = cryptoString;
break;
- case "router-signature":
+ case ROUTER_SIGNATURE:
this.routerSignature = cryptoString;
break;
- case "identity-ed25519":
+ case IDENTITY_ED25519:
this.identityEd25519 = cryptoString;
this.parseIdentityEd25519CryptoBlock(cryptoString);
break;
- case "onion-key-crosscert":
+ case ONION_KEY_CROSSCERT:
this.onionKeyCrosscert = cryptoString;
break;
- case "ntor-onion-key-crosscert":
+ case NTOR_ONION_KEY_CROSSCERT:
this.ntorOnionKeyCrosscert = cryptoString;
break;
default:
@@ -224,8 +227,9 @@ public abstract class ServerDescriptorImpl extends DescriptorImpl
}
}
cryptoLines = null;
- nextCrypto = "";
+ nextCrypto = Key.EMPTY;
break;
+ case INVALID:
default:
if (cryptoLines != null) {
cryptoLines.add(line);
@@ -301,8 +305,8 @@ public abstract class ServerDescriptorImpl extends DescriptorImpl
private void parsePlatformLine(String line, String lineNoOpt,
String[] partsNoOpt) throws DescriptorParseException {
- if (lineNoOpt.length() > "platform ".length()) {
- this.platform = lineNoOpt.substring("platform ".length());
+ if (lineNoOpt.length() > Key.PLATFORM.keyword.length() + 1) {
+ this.platform = lineNoOpt.substring(Key.PLATFORM.keyword.length() + 1);
} else {
this.platform = "";
}
@@ -322,11 +326,12 @@ public abstract class ServerDescriptorImpl extends DescriptorImpl
private void parseFingerprintLine(String line, String lineNoOpt,
String[] partsNoOpt) throws DescriptorParseException {
- if (lineNoOpt.length() != "fingerprint".length() + 5 * 10) {
+ if (lineNoOpt.length() != Key.FINGERPRINT.keyword.length() + 5 * 10) {
throw new DescriptorParseException("Illegal line '" + line + "'.");
}
this.fingerprint = ParseHelper.parseTwentyByteHexString(line,
- lineNoOpt.substring("fingerprint ".length()).replaceAll(" ", ""));
+ lineNoOpt.substring(Key.FINGERPRINT.keyword.length() + 1)
+ .replaceAll(SP, ""));
}
private void parseHibernatingLine(String line, String lineNoOpt,
@@ -358,14 +363,14 @@ public abstract class ServerDescriptorImpl extends DescriptorImpl
private void parseOnionKeyLine(String line, String lineNoOpt,
String[] partsNoOpt) throws DescriptorParseException {
- if (!lineNoOpt.equals("onion-key")) {
+ if (!lineNoOpt.equals(Key.ONION_KEY.keyword)) {
throw new DescriptorParseException("Illegal line '" + line + "'.");
}
}
private void parseSigningKeyLine(String line, String lineNoOpt,
String[] partsNoOpt) throws DescriptorParseException {
- if (!lineNoOpt.equals("signing-key")) {
+ if (!lineNoOpt.equals(Key.SIGNING_KEY.keyword)) {
throw new DescriptorParseException("Illegal line '" + line + "'.");
}
}
@@ -391,15 +396,15 @@ public abstract class ServerDescriptorImpl extends DescriptorImpl
private void parseRouterSignatureLine(String line, String lineNoOpt,
String[] partsNoOpt) throws DescriptorParseException {
- if (!lineNoOpt.equals("router-signature")) {
+ if (!lineNoOpt.equals(Key.ROUTER_SIGNATURE.keyword)) {
throw new DescriptorParseException("Illegal line '" + line + "'.");
}
}
private void parseContactLine(String line, String lineNoOpt,
String[] partsNoOpt) throws DescriptorParseException {
- if (lineNoOpt.length() > "contact ".length()) {
- this.contact = lineNoOpt.substring("contact ".length());
+ if (lineNoOpt.length() > Key.CONTACT.keyword.length() + 1) {
+ this.contact = lineNoOpt.substring(Key.CONTACT.keyword.length() + 1);
} else {
this.contact = "";
}
@@ -455,7 +460,7 @@ public abstract class ServerDescriptorImpl extends DescriptorImpl
private void parseCachesExtraInfoLine(String line, String lineNoOpt,
String[] partsNoOpt) throws DescriptorParseException {
- if (!lineNoOpt.equals("caches-extra-info")) {
+ if (!lineNoOpt.equals(Key.CACHES_EXTRA_INFO.keyword)) {
throw new DescriptorParseException("Illegal line '" + line + "'.");
}
this.cachesExtraInfo = true;
@@ -532,7 +537,7 @@ public abstract class ServerDescriptorImpl extends DescriptorImpl
private void parseAllowSingleHopExitsLine(String line, String lineNoOpt,
String[] partsNoOpt) throws DescriptorParseException {
- if (!lineNoOpt.equals("allow-single-hop-exits")) {
+ if (!lineNoOpt.equals(Key.ALLOW_SINGLE_HOP_EXITS.keyword)) {
throw new DescriptorParseException("Illegal line '" + line + "'.");
}
this.allowSingleHopExits = true;
@@ -568,9 +573,9 @@ public abstract class ServerDescriptorImpl extends DescriptorImpl
if (partsNoOpt.length != 3) {
isValid = false;
} else {
- switch (partsNoOpt[1]) {
- case "accept":
- case "reject":
+ switch (Key.get(partsNoOpt[1])) {
+ case ACCEPT:
+ case REJECT:
this.ipv6DefaultPolicy = partsNoOpt[1];
this.ipv6PortList = partsNoOpt[2];
String[] ports = partsNoOpt[2].split(",", -1);
@@ -581,6 +586,7 @@ public abstract class ServerDescriptorImpl extends DescriptorImpl
}
}
break;
+ case INVALID:
default:
isValid = false;
}
@@ -626,7 +632,7 @@ public abstract class ServerDescriptorImpl extends DescriptorImpl
private void parseTunnelledDirServerLine(String line, String lineNoOpt,
String[] partsNoOpt) throws DescriptorParseException {
- if (!lineNoOpt.equals("tunnelled-dir-server")) {
+ if (!lineNoOpt.equals(Key.TUNNELLED_DIR_SERVER.keyword)) {
throw new DescriptorParseException("Illegal line '" + line + "'.");
}
this.tunnelledDirServer = true;
@@ -684,8 +690,8 @@ public abstract class ServerDescriptorImpl extends DescriptorImpl
}
try {
String ascii = new String(this.getRawDescriptorBytes(), "US-ASCII");
- String startToken = "router ";
- String sigToken = "\nrouter-signature\n";
+ String startToken = Key.ROUTER.keyword + SP;
+ String sigToken = NL + Key.ROUTER_SIGNATURE.keyword + NL;
int start = ascii.indexOf(startToken);
int sig = ascii.indexOf(sigToken) + sigToken.length();
if (start >= 0 && sig >= 0 && sig > start) {
@@ -715,7 +721,7 @@ public abstract class ServerDescriptorImpl extends DescriptorImpl
}
try {
String ascii = new String(this.getRawDescriptorBytes(), "US-ASCII");
- String startToken = "router ";
+ String startToken = Key.ROUTER.keyword + SP;
String sigToken = "\n-----END SIGNATURE-----\n";
int start = ascii.indexOf(startToken);
int sig = ascii.indexOf(sigToken) + sigToken.length();