[tor-commits] [metrics-lib/master] Add support for parsing v2 network statuses.

karsten at torproject.org karsten at torproject.org
Wed May 16 17:43:12 UTC 2012


commit 0eb47d2650b6edf516fc9ec1eb508c08db86ca46
Author: Karsten Loesing <karsten.loesing at gmx.net>
Date:   Wed May 16 17:00:46 2012 +0200

    Add support for parsing v2 network statuses.
---
 .../torproject/descriptor/RelayNetworkStatus.java  |   68 ++++
 .../descriptor/impl/BridgeNetworkStatusImpl.java   |    2 +-
 .../torproject/descriptor/impl/DescriptorImpl.java |    3 +
 .../descriptor/impl/NetworkStatusImpl.java         |   14 +-
 .../impl/RelayNetworkStatusConsensusImpl.java      |    2 +-
 .../descriptor/impl/RelayNetworkStatusImpl.java    |  360 ++++++++++++++++++++
 .../impl/RelayNetworkStatusVoteImpl.java           |   90 ++---
 7 files changed, 475 insertions(+), 64 deletions(-)

diff --git a/src/org/torproject/descriptor/RelayNetworkStatus.java b/src/org/torproject/descriptor/RelayNetworkStatus.java
new file mode 100644
index 0000000..5d05f0c
--- /dev/null
+++ b/src/org/torproject/descriptor/RelayNetworkStatus.java
@@ -0,0 +1,68 @@
+/* Copyright 2012 The Tor Project
+ * See LICENSE for licensing information */
+package org.torproject.descriptor;
+
+import java.util.List;
+import java.util.SortedMap;
+import java.util.SortedSet;
+
+/* Contains a v2 network status. */
+public interface RelayNetworkStatus extends Descriptor {
+
+  /* Return the network status version. */
+  public int getNetworkStatusVersion();
+
+  /* Return the authority's hostname. */
+  public String getHostname();
+
+  /* Return the authority's IP address. */
+  public String getAddress();
+
+  /* Return the authority's directory port. */
+  public int getDirport();
+
+  /* Return the directory's signing key's fingerprint. */
+  public String getFingerprint();
+
+  /* Return the contact line. */
+  public String getContactLine();
+
+  /* Return the directory signing key digest. */
+  public String getDirSigningKey();
+
+  /* Return recommended server versions or null if the status doesn't
+   * contain recommended server versions. */
+  public List<String> getRecommendedServerVersions();
+
+  /* Return recommended client versions or null if the status doesn't
+   * contain recommended client versions. */
+  public List<String> getRecommendedClientVersions();
+
+  /* Return the published time in milliseconds. */
+  public long getPublishedMillis();
+
+  /* Return the set of flags that this directory assigns to relays, or
+   * null if the status does not contain a dir-options line. */
+  public SortedSet<String> getDirOptions();
+
+  /* Return status entries, one for each contained relay. */
+  public SortedMap<String, NetworkStatusEntry> getStatusEntries();
+
+  /* Return whether a status entry with the given fingerprint exists. */
+  public boolean containsStatusEntry(String fingerprint);
+
+  /* Return a status entry by fingerprint or null if no such status entry
+   * exists. */
+  public NetworkStatusEntry getStatusEntry(String fingerprint);
+
+  /* Return the directory nickname. */
+  public String getNickname();
+
+  /* Return the directory signature. */
+  public String getDirectorySignature();
+
+  /* Return the status digest that the directory authority used to sign
+   * the network status. */
+  public String getStatusDigest();
+}
+
diff --git a/src/org/torproject/descriptor/impl/BridgeNetworkStatusImpl.java b/src/org/torproject/descriptor/impl/BridgeNetworkStatusImpl.java
index 1d9818c..e6d1942 100644
--- a/src/org/torproject/descriptor/impl/BridgeNetworkStatusImpl.java
+++ b/src/org/torproject/descriptor/impl/BridgeNetworkStatusImpl.java
@@ -15,7 +15,7 @@ public class BridgeNetworkStatusImpl extends NetworkStatusImpl
   protected BridgeNetworkStatusImpl(byte[] statusBytes,
       String fileName, boolean failUnrecognizedDescriptorLines)
       throws DescriptorParseException {
-    super(statusBytes, failUnrecognizedDescriptorLines);
+    super(statusBytes, failUnrecognizedDescriptorLines, false);
     this.setPublishedMillisFromFileName(fileName);
   }
 
diff --git a/src/org/torproject/descriptor/impl/DescriptorImpl.java b/src/org/torproject/descriptor/impl/DescriptorImpl.java
index 6b1b167..7503419 100644
--- a/src/org/torproject/descriptor/impl/DescriptorImpl.java
+++ b/src/org/torproject/descriptor/impl/DescriptorImpl.java
@@ -66,6 +66,9 @@ public abstract class DescriptorImpl implements Descriptor {
     } else if (firstLines.startsWith("ExitNode ")) {
       parsedDescriptors.add(new ExitListImpl(rawDescriptorBytes, fileName,
           failUnrecognizedDescriptorLines));
+    } else if (firstLines.startsWith("network-status-version 2\n")) {
+      parsedDescriptors.add(new RelayNetworkStatusImpl(rawDescriptorBytes,
+          failUnrecognizedDescriptorLines));
     } else {
       throw new DescriptorParseException("Could not detect descriptor "
           + "type in descriptor starting with '" + firstLines + "'.");
diff --git a/src/org/torproject/descriptor/impl/NetworkStatusImpl.java b/src/org/torproject/descriptor/impl/NetworkStatusImpl.java
index d27e651..35e63b3 100644
--- a/src/org/torproject/descriptor/impl/NetworkStatusImpl.java
+++ b/src/org/torproject/descriptor/impl/NetworkStatusImpl.java
@@ -17,14 +17,14 @@ import org.torproject.descriptor.NetworkStatusEntry;
 public abstract class NetworkStatusImpl extends DescriptorImpl {
 
   protected NetworkStatusImpl(byte[] rawDescriptorBytes,
-      boolean failUnrecognizedDescriptorLines)
-      throws DescriptorParseException {
+      boolean failUnrecognizedDescriptorLines,
+      boolean containsDirSourceEntries) throws DescriptorParseException {
     super(rawDescriptorBytes, failUnrecognizedDescriptorLines);
-    this.splitAndParseParts(rawDescriptorBytes);
+    this.splitAndParseParts(rawDescriptorBytes, containsDirSourceEntries);
   }
 
-  private void splitAndParseParts(byte[] rawDescriptorBytes)
-      throws DescriptorParseException {
+  private void splitAndParseParts(byte[] rawDescriptorBytes,
+      boolean containsDirSourceEntries) throws DescriptorParseException {
     if (this.rawDescriptorBytes.length == 0) {
       throw new DescriptorParseException("Descriptor is empty.");
     }
@@ -34,8 +34,8 @@ public abstract class NetworkStatusImpl extends DescriptorImpl {
       throw new DescriptorParseException("Empty lines are not allowed.");
     }
     int startIndex = 0;
-    int firstDirSourceIndex = this.findFirstIndexOfKeyword(
-        descriptorString, "dir-source");
+    int firstDirSourceIndex = !containsDirSourceEntries ? -1 :
+        this.findFirstIndexOfKeyword(descriptorString, "dir-source");
     int firstRIndex = this.findFirstIndexOfKeyword(descriptorString, "r");
     int directoryFooterIndex = this.findFirstIndexOfKeyword(
         descriptorString, "directory-footer");
diff --git a/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java b/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java
index 3d2af37..14082b8 100644
--- a/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java
+++ b/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java
@@ -41,7 +41,7 @@ public class RelayNetworkStatusConsensusImpl extends NetworkStatusImpl
   protected RelayNetworkStatusConsensusImpl(byte[] consensusBytes,
       boolean failUnrecognizedDescriptorLines)
       throws DescriptorParseException {
-    super(consensusBytes, failUnrecognizedDescriptorLines);
+    super(consensusBytes, failUnrecognizedDescriptorLines, true);
     Set<String> exactlyOnceKeywords = new HashSet<String>(Arrays.asList((
         "vote-status,consensus-method,valid-after,fresh-until,"
         + "valid-until,voting-delay,known-flags").split(",")));
diff --git a/src/org/torproject/descriptor/impl/RelayNetworkStatusImpl.java b/src/org/torproject/descriptor/impl/RelayNetworkStatusImpl.java
new file mode 100644
index 0000000..f3ab34a
--- /dev/null
+++ b/src/org/torproject/descriptor/impl/RelayNetworkStatusImpl.java
@@ -0,0 +1,360 @@
+/* Copyright 2012 The Tor Project
+ * See LICENSE for licensing information */
+package org.torproject.descriptor.impl;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.torproject.descriptor.RelayNetworkStatus;
+
+/* TODO Write unit tests. */
+
+public class RelayNetworkStatusImpl extends NetworkStatusImpl
+    implements RelayNetworkStatus {
+
+  protected static List<RelayNetworkStatus> parseStatuses(
+      byte[] statusesBytes, boolean failUnrecognizedDescriptorLines)
+      throws DescriptorParseException {
+    List<RelayNetworkStatus> parsedStatuses =
+        new ArrayList<RelayNetworkStatus>();
+    List<byte[]> splitStatusBytes =
+        DescriptorImpl.splitRawDescriptorBytes(statusesBytes,
+        "network-status-version 2");
+    for (byte[] statusBytes : splitStatusBytes) {
+      RelayNetworkStatus parsedStatus = new RelayNetworkStatusImpl(
+          statusBytes, failUnrecognizedDescriptorLines);
+      parsedStatuses.add(parsedStatus);
+    }
+    return parsedStatuses;
+  }
+
+  protected RelayNetworkStatusImpl(byte[] statusBytes,
+      boolean failUnrecognizedDescriptorLines)
+      throws DescriptorParseException {
+    super(statusBytes, failUnrecognizedDescriptorLines, false);
+    Set<String> exactlyOnceKeywords = new HashSet<String>(Arrays.asList((
+        "network-status-version,dir-source,fingerprint,contact,"
+        + "dir-signing-key,published").split(",")));
+    this.checkExactlyOnceKeywords(exactlyOnceKeywords);
+    Set<String> atMostOnceKeywords = new HashSet<String>(Arrays.asList(
+        "dir-options,client-versions,server-versions".split(",")));
+    this.checkAtMostOnceKeywords(atMostOnceKeywords);
+    this.checkFirstKeyword("network-status-version");
+    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 ";
+      if (!ascii.contains(sigToken)) {
+        return;
+      }
+      int start = ascii.indexOf(startToken);
+      int sig = ascii.indexOf(sigToken) + sigToken.length();
+      sig = ascii.indexOf("\n", sig) + 1;
+      if (start >= 0 && sig >= 0 && sig > start) {
+        byte[] forDigest = new byte[sig - start];
+        System.arraycopy(this.getRawDescriptorBytes(), start,
+            forDigest, 0, sig - start);
+        this.statusDigest = DigestUtils.shaHex(forDigest);
+      }
+    } catch (UnsupportedEncodingException e) {
+      /* Handle below. */
+    }
+    if (this.statusDigest == null) {
+      throw new DescriptorParseException("Could not calculate status "
+          + "digest.");
+    }
+  }
+
+  protected void parseHeader(byte[] headerBytes)
+      throws DescriptorParseException {
+    Scanner s = new Scanner(new String(headerBytes)).useDelimiter("\n");
+    String nextCrypto = null;
+    StringBuilder crypto = null;
+    while (s.hasNext()) {
+      String line = s.next();
+      String[] parts = line.split(" ");
+      String keyword = parts[0];
+      if (keyword.equals("network-status-version")) {
+        this.parseNetworkStatusVersionLine(line, parts);
+      } else if (keyword.equals("dir-source")) {
+        this.parseDirSourceLine(line, parts);
+      } else if (keyword.equals("fingerprint")) {
+        this.parseFingerprintLine(line, parts);
+      } else if (keyword.equals("contact")) {
+        this.parseContactLine(line, parts);
+      } else if (keyword.equals("dir-signing-key")) {
+        this.parseDirSigningKeyLine(line, parts);
+        nextCrypto = "dir-signing-key";
+      } else if (keyword.equals("client-versions")) {
+        this.parseClientVersionsLine(line, parts);
+      } else if (keyword.equals("server-versions")) {
+        this.parseServerVersionsLine(line, parts);
+      } else if (keyword.equals("published")) {
+        this.parsePublishedLine(line, parts);
+      } else if (keyword.equals("dir-options")) {
+        this.parseDirOptionsLine(line, parts);
+      } else if (line.startsWith("-----BEGIN")) {
+        crypto = new StringBuilder();
+        crypto.append(line + "\n");
+      } else if (line.startsWith("-----END")) {
+        crypto.append(line + "\n");
+        String cryptoString = crypto.toString();
+        crypto = null;
+        if (nextCrypto.equals("dir-signing-key")) {
+          this.dirSigningKey = cryptoString;
+        } else {
+          throw new DescriptorParseException("Unrecognized crypto "
+              + "block in v2 network status.");
+        }
+        nextCrypto = null;
+      } else if (crypto != null) {
+        crypto.append(line + "\n");
+      } else if (this.failUnrecognizedDescriptorLines) {
+        throw new DescriptorParseException("Unrecognized line '" + line
+            + "' in v2 network status.");
+      } else {
+        if (this.unrecognizedLines == null) {
+          this.unrecognizedLines = new ArrayList<String>();
+        }
+        this.unrecognizedLines.add(line);
+      }
+    }
+  }
+
+  protected void parseFooter(byte[] footerBytes)
+      throws DescriptorParseException {
+    throw new DescriptorParseException("No directory footer expected in "
+        + "v2 network status.");
+  }
+
+  protected void parseDirectorySignature(byte[] directorySignatureBytes)
+      throws DescriptorParseException {
+    Scanner s = new Scanner(new String(directorySignatureBytes)).
+        useDelimiter("\n");
+    String nextCrypto = null;
+    StringBuilder crypto = null;
+    while (s.hasNext()) {
+      String line = s.next();
+      String[] parts = line.split(" ");
+      String keyword = parts[0];
+      if (keyword.equals("directory-signature")) {
+        this.parseDirectorySignatureLine(line, parts);
+        nextCrypto = "directory-signature";
+      } else if (line.startsWith("-----BEGIN")) {
+        crypto = new StringBuilder();
+        crypto.append(line + "\n");
+      } else if (line.startsWith("-----END")) {
+        crypto.append(line + "\n");
+        String cryptoString = crypto.toString();
+        crypto = null;
+        if (nextCrypto.equals("directory-signature")) {
+          this.directorySignature = cryptoString;
+        } else {
+          throw new DescriptorParseException("Unrecognized crypto "
+              + "block in v2 network status.");
+        }
+        nextCrypto = null;
+      } else if (crypto != null) {
+        crypto.append(line + "\n");
+      } else if (this.failUnrecognizedDescriptorLines) {
+        throw new DescriptorParseException("Unrecognized line '" + line
+            + "' in v2 network status.");
+      } else {
+        if (this.unrecognizedLines == null) {
+          this.unrecognizedLines = new ArrayList<String>();
+        }
+        this.unrecognizedLines.add(line);
+      }
+    }
+  }
+
+  private void parseNetworkStatusVersionLine(String line, String[] parts)
+      throws DescriptorParseException {
+    if (!line.equals("network-status-version 2")) {
+      throw new DescriptorParseException("Illegal network status version "
+          + "number in line '" + line + "'.");
+    }
+    this.networkStatusVersion = 2;
+  }
+
+  private void parseDirSourceLine(String line, String[] parts)
+      throws DescriptorParseException {
+    if (parts.length != 4) {
+      throw new DescriptorParseException("Illegal line '" + line
+          + "' in v2 network status.");
+    }
+    if (parts[1].length() < 1) {
+      throw new DescriptorParseException("Illegal hostname in '" + line
+          + "'.");
+    }
+    this.address = ParseHelper.parseIpv4Address(line, parts[2]);
+    this.dirPort = ParseHelper.parsePort(line, parts[3]);
+  }
+
+
+  private void parseFingerprintLine(String line, String[] parts)
+      throws DescriptorParseException {
+    if (parts.length != 2) {
+      throw new DescriptorParseException("Illegal line '" + line
+          + "' in v2 network status.");
+    }
+    this.fingerprint = ParseHelper.parseTwentyByteHexString(line,
+        parts[1]);
+  }
+
+  private void parseContactLine(String line, String[] parts)
+      throws DescriptorParseException {
+    if (line.length() > "contact ".length()) {
+      this.contactLine = line.substring("contact ".length());
+    } else {
+      this.contactLine = "";
+    }
+  }
+
+  private void parseDirSigningKeyLine(String line, String[] parts)
+      throws DescriptorParseException {
+    if (!line.equals("dir-signing-key")) {
+      throw new DescriptorParseException("Illegal line '" + line + "'.");
+    }
+  }
+
+  private void parseClientVersionsLine(String line, String[] parts)
+      throws DescriptorParseException {
+    this.recommendedClientVersions = this.parseClientOrServerVersions(
+        line, parts);
+  }
+
+  private void parseServerVersionsLine(String line, String[] parts)
+      throws DescriptorParseException {
+    this.recommendedServerVersions = this.parseClientOrServerVersions(
+        line, parts);
+  }
+
+  private List<String> parseClientOrServerVersions(String line,
+      String[] parts) throws DescriptorParseException {
+    List<String> result = new ArrayList<String>();
+    if (parts.length == 1) {
+      return result;
+    } else if (parts.length > 2) {
+      throw new DescriptorParseException("Illegal versions line '" + line
+          + "'.");
+    }
+    String[] versions = parts[1].split(",", -1);
+    for (int i = 0; i < versions.length; i++) {
+      String version = versions[i];
+      if (version.length() < 1) {
+        throw new DescriptorParseException("Illegal versions line '"
+            + line + "'.");
+      }
+      result.add(version);
+    }
+    return result;
+  }
+
+  private void parsePublishedLine(String line, String[] parts)
+      throws DescriptorParseException {
+    this.publishedMillis = ParseHelper.parseTimestampAtIndex(line, parts,
+        1, 2);
+  }
+
+  private void parseDirOptionsLine(String line, String[] parts)
+      throws DescriptorParseException {
+    this.dirOptions = new TreeSet<String>();
+    for (int i = 1; i < parts.length; i++) {
+      this.dirOptions.add(parts[i]);
+    }
+  }
+
+  private void parseDirectorySignatureLine(String line, String[] parts)
+      throws DescriptorParseException {
+    if (parts.length < 2) {
+      throw new DescriptorParseException("Illegal line '" + line + "'.");
+    }
+    this.nickname = ParseHelper.parseNickname(line, parts[1]);
+  }
+
+  private String statusDigest;
+  public String getStatusDigest() {
+    return this.statusDigest;
+  }
+
+  private int networkStatusVersion;
+  public int getNetworkStatusVersion() {
+    return this.networkStatusVersion;
+  }
+
+  private String hostname;
+  public String getHostname() {
+    return this.hostname;
+  }
+
+  private String address;
+  public String getAddress() {
+    return this.address;
+  }
+
+  private int dirPort;
+  public int getDirport() {
+    return this.dirPort;
+  }
+
+  private String fingerprint;
+  public String getFingerprint() {
+    return this.fingerprint;
+  }
+
+  private String contactLine;
+  public String getContactLine() {
+    return this.contactLine;
+  }
+
+  private String dirSigningKey;
+  public String getDirSigningKey() {
+    return this.dirSigningKey;
+  }
+
+  private List<String> recommendedClientVersions;
+  public List<String> getRecommendedClientVersions() {
+    return this.recommendedClientVersions == null ? null :
+        new ArrayList<String>(this.recommendedClientVersions);
+  }
+
+  private List<String> recommendedServerVersions;
+  public List<String> getRecommendedServerVersions() {
+    return this.recommendedServerVersions == null ? null :
+        new ArrayList<String>(this.recommendedServerVersions);
+  }
+
+  private long publishedMillis;
+  public long getPublishedMillis() {
+    return this.publishedMillis;
+  }
+
+  private SortedSet<String> dirOptions;
+  public SortedSet<String> getDirOptions() {
+    return new TreeSet<String>(this.dirOptions);
+  }
+
+  private String nickname;
+  public String getNickname() {
+    return this.nickname;
+  }
+
+  private String directorySignature;
+  public String getDirectorySignature() {
+    return this.directorySignature;
+  }
+}
+
diff --git a/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java b/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
index 5791688..7cce313 100644
--- a/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
+++ b/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
@@ -39,7 +39,7 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
   protected RelayNetworkStatusVoteImpl(byte[] voteBytes,
       boolean failUnrecognizedDescriptorLines)
       throws DescriptorParseException {
-    super(voteBytes, failUnrecognizedDescriptorLines);
+    super(voteBytes, failUnrecognizedDescriptorLines, false);
     Set<String> exactlyOnceKeywords = new HashSet<String>(Arrays.asList((
         "vote-status,consensus-methods,published,valid-after,fresh-until,"
         + "valid-until,voting-delay,known-flags,dir-source,"
@@ -57,6 +57,7 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
   protected void parseHeader(byte[] headerBytes)
       throws DescriptorParseException {
     Scanner s = new Scanner(new String(headerBytes)).useDelimiter("\n");
+    boolean skipCrypto = false; /* TODO Parse crypto parts. */
     while (s.hasNext()) {
       String line = s.next();
       String[] parts = line.split(" ");
@@ -85,14 +86,40 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
         this.parseKnownFlagsLine(line, parts);
       } else if (keyword.equals("params")) {
         this.parseParamsLine(line, parts);
-      } else if (this.failUnrecognizedDescriptorLines) {
-        throw new DescriptorParseException("Unrecognized line '" + line
-            + "' in vote.");
-      } else {
-        if (this.unrecognizedLines == null) {
-          this.unrecognizedLines = new ArrayList<String>();
+      } else if (keyword.equals("dir-source")) {
+        this.parseDirSourceLine(line, parts);
+      } else if (keyword.equals("contact")) {
+        this.parseContactLine(line, parts);
+      } else if (keyword.equals("dir-key-certificate-version")) {
+        this.parseDirKeyCertificateVersionLine(line, parts);
+      } else if (keyword.equals("dir-address")) {
+        this.parseDirAddressLine(line, parts);
+      } else if (keyword.equals("fingerprint")) {
+        this.parseFingerprintLine(line, parts);
+      } else if (keyword.equals("legacy-dir-key")) {
+        this.parseLegacyDirKeyLine(line, parts);
+      } else if (keyword.equals("dir-key-published")) {
+        this.parseDirKeyPublished(line, parts);
+      } else if (keyword.equals("dir-key-expires")) {
+        this.parseDirKeyExpiresLine(line, parts);
+      } else if (keyword.equals("dir-identity-key") ||
+          keyword.equals("dir-signing-key") ||
+          keyword.equals("dir-key-crosscert") ||
+          keyword.equals("dir-key-certification")) {
+      } else if (line.startsWith("-----BEGIN")) {
+        skipCrypto = true;
+      } else if (line.startsWith("-----END")) {
+        skipCrypto = false;
+      } else if (!skipCrypto) {
+        if (this.failUnrecognizedDescriptorLines) {
+          throw new DescriptorParseException("Unrecognized line '"
+              + line + "' in vote.");
+        } else {
+          if (this.unrecognizedLines == null) {
+            this.unrecognizedLines = new ArrayList<String>();
+          }
+          this.unrecognizedLines.add(line);
         }
-        this.unrecognizedLines.add(line);
       }
     }
   }
@@ -225,53 +252,6 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
     this.consensusParams = ParseHelper.parseKeyValuePairs(line, parts, 1);
   }
 
-  protected void parseDirSource(byte[] dirSourceBytes)
-      throws DescriptorParseException {
-    Scanner s = new Scanner(new String(dirSourceBytes)).
-        useDelimiter("\n");
-    boolean skipCrypto = false;
-    while (s.hasNext()) {
-      String line = s.next();
-      String[] parts = line.split(" ");
-      String keyword = parts[0];
-      if (keyword.equals("dir-source")) {
-        this.parseDirSourceLine(line, parts);
-      } else if (keyword.equals("contact")) {
-        this.parseContactLine(line, parts);
-      } else if (keyword.equals("dir-key-certificate-version")) {
-        this.parseDirKeyCertificateVersionLine(line, parts);
-      } else if (keyword.equals("dir-address")) {
-        this.parseDirAddressLine(line, parts);
-      } else if (keyword.equals("fingerprint")) {
-        this.parseFingerprintLine(line, parts);
-      } else if (keyword.equals("legacy-dir-key")) {
-        this.parseLegacyDirKeyLine(line, parts);
-      } else if (keyword.equals("dir-key-published")) {
-        this.parseDirKeyPublished(line, parts);
-      } else if (keyword.equals("dir-key-expires")) {
-        this.parseDirKeyExpiresLine(line, parts);
-      } else if (keyword.equals("dir-identity-key") ||
-          keyword.equals("dir-signing-key") ||
-          keyword.equals("dir-key-crosscert") ||
-          keyword.equals("dir-key-certification")) {
-      } else if (line.startsWith("-----BEGIN")) {
-        skipCrypto = true;
-      } else if (line.startsWith("-----END")) {
-        skipCrypto = false;
-      } else if (!skipCrypto) {
-        if (this.failUnrecognizedDescriptorLines) {
-          throw new DescriptorParseException("Unrecognized line '"
-              + line + "' in vote.");
-        } else {
-          if (this.unrecognizedLines == null) {
-            this.unrecognizedLines = new ArrayList<String>();
-          }
-          this.unrecognizedLines.add(line);
-        }
-      }
-    }
-  }
-
   private void parseDirSourceLine(String line, String[] parts)
       throws DescriptorParseException {
     if (parts.length != 7) {





More information about the tor-commits mailing list