commit ef6de2f9ad26fb064844d3c6edccf6ce7a829faf Author: Karsten Loesing karsten.loesing@gmx.net Date: Thu Jan 12 09:59:32 2012 +0100
Use a single relay and bridge descriptor implementation.
Relay and bridge server and extra-info descriptors are similar enough to implement them in a single class each. It should be clear from the descriptor source (relay or bridge reader) whether the descriptor was published by a relay or a bridge. --- .../descriptor/BridgeExtraInfoDescriptor.java | 7 - .../descriptor/BridgeServerDescriptor.java | 7 - .../torproject/descriptor/ExtraInfoDescriptor.java | 211 ++++ .../descriptor/RelayExtraInfoDescriptor.java | 211 ---- .../descriptor/RelayServerDescriptor.java | 110 -- .../torproject/descriptor/ServerDescriptor.java | 110 ++ .../torproject/descriptor/impl/DescriptorImpl.java | 4 +- .../descriptor/impl/ExtraInfoDescriptorImpl.java | 574 +++++++++++ .../impl/RelayExtraInfoDescriptorImpl.java | 574 ----------- .../descriptor/impl/RelayServerDescriptorImpl.java | 532 ---------- .../descriptor/impl/ServerDescriptorImpl.java | 532 ++++++++++ .../impl/RelayServerDescriptorImplTest.java | 1080 -------------------- .../descriptor/impl/ServerDescriptorImplTest.java | 1080 ++++++++++++++++++++ 13 files changed, 2509 insertions(+), 2523 deletions(-)
diff --git a/src/org/torproject/descriptor/BridgeExtraInfoDescriptor.java b/src/org/torproject/descriptor/BridgeExtraInfoDescriptor.java deleted file mode 100644 index ed0238d..0000000 --- a/src/org/torproject/descriptor/BridgeExtraInfoDescriptor.java +++ /dev/null @@ -1,7 +0,0 @@ -/* Copyright 2011, 2012 The Tor Project - * See LICENSE for licensing information */ -package org.torproject.descriptor; - -public interface BridgeExtraInfoDescriptor extends Descriptor { -} - diff --git a/src/org/torproject/descriptor/BridgeServerDescriptor.java b/src/org/torproject/descriptor/BridgeServerDescriptor.java deleted file mode 100644 index ec759b1..0000000 --- a/src/org/torproject/descriptor/BridgeServerDescriptor.java +++ /dev/null @@ -1,7 +0,0 @@ -/* Copyright 2011, 2012 The Tor Project - * See LICENSE for licensing information */ -package org.torproject.descriptor; - -public interface BridgeServerDescriptor extends Descriptor { -} - diff --git a/src/org/torproject/descriptor/ExtraInfoDescriptor.java b/src/org/torproject/descriptor/ExtraInfoDescriptor.java new file mode 100644 index 0000000..bd4bcd8 --- /dev/null +++ b/src/org/torproject/descriptor/ExtraInfoDescriptor.java @@ -0,0 +1,211 @@ +/* Copyright 2012 The Tor Project + * See LICENSE for licensing information */ +package org.torproject.descriptor; + +import java.util.List; +import java.util.SortedMap; + +public interface ExtraInfoDescriptor extends Descriptor { + + /* Return the relay's nickname. */ + public String getNickname(); + + /* Return the relay's fingerprint. */ + public String getFingerprint(); + + /* Return the publication time of this descriptor. */ + public long getPublishedMillis(); + + /* Return the read history contained in this descriptor, or null if no + * read history is contained. */ + public BandwidthHistory getReadHistory(); + + /* Return the write history contained in this descriptor, or null if no + * read history is contained. */ + public BandwidthHistory getWriteHistory(); + + /* Return the SHA1 digest of the GeoIP database used by this relay, or + * null if no GeoIP database digest is included. */ + public String getGeoipDbDigest(); + + /* Return the end of the included directory request statistics interval, + * or -1 if no directory request statistics are included. */ + public long getDirreqStatsEndMillis(); + + /* Return the interval length of the included directory request + * statistics, or -1 if no directory request statistics are included. */ + public long getDirreqStatsIntervalLength(); + + /* Return statistics on unique IP addresses requesting v2 network + * statuses with map keys being country codes and map values being + * numbers of unique IP addresses rounded up to the nearest multiple of + * 8, or null if no such statistics are included. */ + public SortedMap<String, Integer> getDirreqV2Ips(); + + /* Return statistics on unique IP addresses requesting v3 network status + * consensuses with map keys being country codes and map values being + * numbers of unique IP addresses rounded up to the nearest multiple of + * 8, or null if no such statistics are included. */ + public SortedMap<String, Integer> getDirreqV3Ips(); + + /* Return statistics on directory requests for v2 network statuses with + * map keys being country codes and map values being request numbers + * rounded up to the nearest multiple of 8, or null if no such + * statistics are included. */ + public SortedMap<String, Integer> getDirreqV2Reqs(); + + /* Return statistics on directory requests for v3 network status + * consensuses with map keys being country codes and map values being + * request numbers rounded up to the nearest multiple of 8, or null if + * no such statistics are included. */ + public SortedMap<String, Integer> getDirreqV3Reqs(); + + /* Return the share of requests for v2 network statuses that the + * directory expects to receive from clients, or -1.0 if no such + * statistics are included. */ + public double getDirreqV2Share(); + + /* Return the share of requests for v3 network status consensuses that + * the directory expects to receive from clients, or -1.0 if no such + * statistics are included. */ + public double getDirreqV3Share(); + + /* Return statistics on directory request responses for v2 network + * statuses with map keys being response strings and map values being + * response numbers rounded up to the nearest multiple of 4, or null if + * no such statistics are included. */ + public SortedMap<String, Integer> getDirreqV2Resp(); + + /* Return statistics on directory request responses for v3 network + * status consensuses with map keys being response strings and map + * values being response numbers rounded up to the nearest multiple of + * 4, or null if no such statistics are included. */ + public SortedMap<String, Integer> getDirreqV3Resp(); + + /* Return statistics on direct directory requests asking for v2 network + * statuses with map keys being statistic keys and map values being + * statistic values, or null if no such statistics are included. */ + public SortedMap<String, Integer> getDirreqV2DirectDl(); + + /* Return statistics on direct directory requests asking for v3 network + * status consensuses with map keys being statistic keys and map + * values being statistic values, or null if no such statistics are + * included. */ + public SortedMap<String, Integer> getDirreqV3DirectDl(); + + /* Return statistics on tunneled directory requests asking for v2 + * network statuses with map keys being statistic keys and map values + * being statistic values, or null if no such statistics are + * included. */ + public SortedMap<String, Integer> getDirreqV2TunneledDl(); + + /* Return statistics on tunneled directory requests asking for v3 + * network status consensuses with map keys being statistic keys and map + * values being statistic values, or null if no such statistics are + * included. */ + public SortedMap<String, Integer> getDirreqV3TunneledDl(); + + /* Return the directory request read history contained in this + * descriptor, or null if no directory request read history is + * contained. */ + public BandwidthHistory getDirreqReadHistory(); + + /* Return the directory request write history contained in this + * descriptor, or null if no directory request write history is + * contained. */ + public BandwidthHistory getDirreqWriteHistory(); + + /* Return the end of the included entry statistics interval, or -1 if no + * entry statistics are included. */ + public long getEntryStatsEndMillis(); + + /* Return the interval length of the included entry statistics, or -1 if + * no entry statistics are included. */ + public long getEntryStatsIntervalLength(); + + /* Return statistics on client IP addresses with map keys being country + * codes and map values being the number of unique IP addresses that + * have connected from that country rounded up to the nearest multiple + * of 8, or null if no entry statistics are included. */ + public SortedMap<String, Integer> getEntryIps(); + + /* Return the end of the included cell statistics interval, or -1 if no + * cell statistics are included. */ + public long getCellStatsEndMillis(); + + /* Return the interval length of the included cell statistics, or -1 if + * no cell statistics are included. */ + public long getCellStatsIntervalLength(); + + /* Return the mean number of processed cells per circuit by circuit + * deciles. */ + public List<Integer> getCellProcessedCells(); + + /* Return the mean number of cells contained in circuit queues by + * circuit deciles. */ + public List<Integer> getCellQueueCells(); + + /* Return the mean times in milliseconds that cells spend in circuit + * queues by circuit deciles. */ + public List<Integer> getCellTimeInQueue(); + + /* Return the mean number of circuits included in any of the cell + * statistics deciles, or -1 if no cell statistics are included. */ + public int getCellCircuitsPerDecile(); + + /* Return the end of the included statistics interval on bi-directional + * connection usage, or -1 if no such statistics are included. */ + public long getConnBiDirectStatsEndMillis(); + + /* Return the interval length of the included statistics on + * bi-directional connection usage, or -1 if no such statistics are + * included. */ + public long getConnBiDirectIntervalLength(); + + /* Return the number of connections on which this relay read and wrote + * less than 2 KiB/s in a 10-second interval, or -1 if no statistics on + * bi-directional connection usage are included. */ + public int getConnBiDirectBelow(); + + /* Return the number of connections on which this relay read and wrote + * at least 2 KiB/s in a 10-second interval and at least 10 times more + * in read direction than in write direction, or -1 if no statistics on + * bi-directional connection usage are included. */ + public int getConnBiDirectRead(); + + /* Return the number of connections on which this relay read and wrote + * at least 2 KiB/s in a 10-second interval and at least 10 times more + * in write direction than in read direction, or -1 if no statistics on + * bi-directional connection usage are included. */ + public int getConnBiDirectWrite(); + + /* Return the number of connections on which this relay read and wrote + * at least 2 KiB/s in a 10-second interval but not 10 times more in + * either direction, or -1 if no statistics on bi-directional connection + * usage are included. */ + public int getConnBiDirectBoth(); + + /* Return the end of the included exit statistics interval, or -1 if no + * exit statistics are included. */ + public long getExitStatsEndMillis(); + + /* Return the interval length of the included exit statistics, or -1 if + * no exit statistics are included. */ + public long getExitStatsIntervalLength(); + + /* Return statistics on KiB written by port with map keys being ports + * and map values being KiB rounded up to the next full KiB, or null if + * no exit statistics are included. */ + public SortedMap<Integer, Integer> getExitKibibytesWritten(); + + /* Return statistics on KiB read by port with map keys being ports and + * map values being KiB rounded up to the next full KiB, or null if no + * exit statistics are included. */ + public SortedMap<Integer, Integer> getExitKibibytesRead(); + + /* Return statistics on opened exit streams with map keys being ports + * and map values being the number of opened streams, rounded up to the + * nearest multiple of 4, or null if no exit statistics are included. */ + public SortedMap<Integer, Integer> getExitStreamsOpened(); +} + diff --git a/src/org/torproject/descriptor/RelayExtraInfoDescriptor.java b/src/org/torproject/descriptor/RelayExtraInfoDescriptor.java deleted file mode 100644 index 853a60a..0000000 --- a/src/org/torproject/descriptor/RelayExtraInfoDescriptor.java +++ /dev/null @@ -1,211 +0,0 @@ -/* Copyright 2012 The Tor Project - * See LICENSE for licensing information */ -package org.torproject.descriptor; - -import java.util.List; -import java.util.SortedMap; - -public interface RelayExtraInfoDescriptor extends Descriptor { - - /* Return the relay's nickname. */ - public String getNickname(); - - /* Return the relay's fingerprint. */ - public String getFingerprint(); - - /* Return the publication time of this descriptor. */ - public long getPublishedMillis(); - - /* Return the read history contained in this descriptor, or null if no - * read history is contained. */ - public BandwidthHistory getReadHistory(); - - /* Return the write history contained in this descriptor, or null if no - * read history is contained. */ - public BandwidthHistory getWriteHistory(); - - /* Return the SHA1 digest of the GeoIP database used by this relay, or - * null if no GeoIP database digest is included. */ - public String getGeoipDbDigest(); - - /* Return the end of the included directory request statistics interval, - * or -1 if no directory request statistics are included. */ - public long getDirreqStatsEndMillis(); - - /* Return the interval length of the included directory request - * statistics, or -1 if no directory request statistics are included. */ - public long getDirreqStatsIntervalLength(); - - /* Return statistics on unique IP addresses requesting v2 network - * statuses with map keys being country codes and map values being - * numbers of unique IP addresses rounded up to the nearest multiple of - * 8, or null if no such statistics are included. */ - public SortedMap<String, Integer> getDirreqV2Ips(); - - /* Return statistics on unique IP addresses requesting v3 network status - * consensuses with map keys being country codes and map values being - * numbers of unique IP addresses rounded up to the nearest multiple of - * 8, or null if no such statistics are included. */ - public SortedMap<String, Integer> getDirreqV3Ips(); - - /* Return statistics on directory requests for v2 network statuses with - * map keys being country codes and map values being request numbers - * rounded up to the nearest multiple of 8, or null if no such - * statistics are included. */ - public SortedMap<String, Integer> getDirreqV2Reqs(); - - /* Return statistics on directory requests for v3 network status - * consensuses with map keys being country codes and map values being - * request numbers rounded up to the nearest multiple of 8, or null if - * no such statistics are included. */ - public SortedMap<String, Integer> getDirreqV3Reqs(); - - /* Return the share of requests for v2 network statuses that the - * directory expects to receive from clients, or -1.0 if no such - * statistics are included. */ - public double getDirreqV2Share(); - - /* Return the share of requests for v3 network status consensuses that - * the directory expects to receive from clients, or -1.0 if no such - * statistics are included. */ - public double getDirreqV3Share(); - - /* Return statistics on directory request responses for v2 network - * statuses with map keys being response strings and map values being - * response numbers rounded up to the nearest multiple of 4, or null if - * no such statistics are included. */ - public SortedMap<String, Integer> getDirreqV2Resp(); - - /* Return statistics on directory request responses for v3 network - * status consensuses with map keys being response strings and map - * values being response numbers rounded up to the nearest multiple of - * 4, or null if no such statistics are included. */ - public SortedMap<String, Integer> getDirreqV3Resp(); - - /* Return statistics on direct directory requests asking for v2 network - * statuses with map keys being statistic keys and map values being - * statistic values, or null if no such statistics are included. */ - public SortedMap<String, Integer> getDirreqV2DirectDl(); - - /* Return statistics on direct directory requests asking for v3 network - * status consensuses with map keys being statistic keys and map - * values being statistic values, or null if no such statistics are - * included. */ - public SortedMap<String, Integer> getDirreqV3DirectDl(); - - /* Return statistics on tunneled directory requests asking for v2 - * network statuses with map keys being statistic keys and map values - * being statistic values, or null if no such statistics are - * included. */ - public SortedMap<String, Integer> getDirreqV2TunneledDl(); - - /* Return statistics on tunneled directory requests asking for v3 - * network status consensuses with map keys being statistic keys and map - * values being statistic values, or null if no such statistics are - * included. */ - public SortedMap<String, Integer> getDirreqV3TunneledDl(); - - /* Return the directory request read history contained in this - * descriptor, or null if no directory request read history is - * contained. */ - public BandwidthHistory getDirreqReadHistory(); - - /* Return the directory request write history contained in this - * descriptor, or null if no directory request write history is - * contained. */ - public BandwidthHistory getDirreqWriteHistory(); - - /* Return the end of the included entry statistics interval, or -1 if no - * entry statistics are included. */ - public long getEntryStatsEndMillis(); - - /* Return the interval length of the included entry statistics, or -1 if - * no entry statistics are included. */ - public long getEntryStatsIntervalLength(); - - /* Return statistics on client IP addresses with map keys being country - * codes and map values being the number of unique IP addresses that - * have connected from that country rounded up to the nearest multiple - * of 8, or null if no entry statistics are included. */ - public SortedMap<String, Integer> getEntryIps(); - - /* Return the end of the included cell statistics interval, or -1 if no - * cell statistics are included. */ - public long getCellStatsEndMillis(); - - /* Return the interval length of the included cell statistics, or -1 if - * no cell statistics are included. */ - public long getCellStatsIntervalLength(); - - /* Return the mean number of processed cells per circuit by circuit - * deciles. */ - public List<Integer> getCellProcessedCells(); - - /* Return the mean number of cells contained in circuit queues by - * circuit deciles. */ - public List<Integer> getCellQueueCells(); - - /* Return the mean times in milliseconds that cells spend in circuit - * queues by circuit deciles. */ - public List<Integer> getCellTimeInQueue(); - - /* Return the mean number of circuits included in any of the cell - * statistics deciles, or -1 if no cell statistics are included. */ - public int getCellCircuitsPerDecile(); - - /* Return the end of the included statistics interval on bi-directional - * connection usage, or -1 if no such statistics are included. */ - public long getConnBiDirectStatsEndMillis(); - - /* Return the interval length of the included statistics on - * bi-directional connection usage, or -1 if no such statistics are - * included. */ - public long getConnBiDirectIntervalLength(); - - /* Return the number of connections on which this relay read and wrote - * less than 2 KiB/s in a 10-second interval, or -1 if no statistics on - * bi-directional connection usage are included. */ - public int getConnBiDirectBelow(); - - /* Return the number of connections on which this relay read and wrote - * at least 2 KiB/s in a 10-second interval and at least 10 times more - * in read direction than in write direction, or -1 if no statistics on - * bi-directional connection usage are included. */ - public int getConnBiDirectRead(); - - /* Return the number of connections on which this relay read and wrote - * at least 2 KiB/s in a 10-second interval and at least 10 times more - * in write direction than in read direction, or -1 if no statistics on - * bi-directional connection usage are included. */ - public int getConnBiDirectWrite(); - - /* Return the number of connections on which this relay read and wrote - * at least 2 KiB/s in a 10-second interval but not 10 times more in - * either direction, or -1 if no statistics on bi-directional connection - * usage are included. */ - public int getConnBiDirectBoth(); - - /* Return the end of the included exit statistics interval, or -1 if no - * exit statistics are included. */ - public long getExitStatsEndMillis(); - - /* Return the interval length of the included exit statistics, or -1 if - * no exit statistics are included. */ - public long getExitStatsIntervalLength(); - - /* Return statistics on KiB written by port with map keys being ports - * and map values being KiB rounded up to the next full KiB, or null if - * no exit statistics are included. */ - public SortedMap<Integer, Integer> getExitKibibytesWritten(); - - /* Return statistics on KiB read by port with map keys being ports and - * map values being KiB rounded up to the next full KiB, or null if no - * exit statistics are included. */ - public SortedMap<Integer, Integer> getExitKibibytesRead(); - - /* Return statistics on opened exit streams with map keys being ports - * and map values being the number of opened streams, rounded up to the - * nearest multiple of 4, or null if no exit statistics are included. */ - public SortedMap<Integer, Integer> getExitStreamsOpened(); -} - diff --git a/src/org/torproject/descriptor/RelayServerDescriptor.java b/src/org/torproject/descriptor/RelayServerDescriptor.java deleted file mode 100644 index 2f48def..0000000 --- a/src/org/torproject/descriptor/RelayServerDescriptor.java +++ /dev/null @@ -1,110 +0,0 @@ -/* Copyright 2011, 2012 The Tor Project - * See LICENSE for licensing information */ -package org.torproject.descriptor; - -import java.util.List; - -/* Contains a relay server descriptor. */ -public interface RelayServerDescriptor extends Descriptor { - - /* Return the relay's nickname. */ - public String getNickname(); - - /* Return the relay's IPv4 address in dotted-quad format. */ - public String getAddress(); - - /* Return the relay's OR port. */ - public int getOrPort(); - - /* Return the relay's SOCKS port which should always be 0. */ - public int getSocksPort(); - - /* Return the relay's directory port. */ - public int getDirPort(); - - /* Return the average bandwidth in bytes per second that the relay is - * willing to sustain over long periods. */ - public int getBandwidthRate(); - - /* Return the burst bandwidth in bytes per second that the relay is - * willing to sustain in very short intervals. */ - public int getBandwidthBurst(); - - /* Return the observed bandwidth in bytes per second as an estimate of - * the capacity that the relay can handle. */ - public int getBandwidthObserved(); - - /* Return the platform string containing the Tor software version and - * the operating system. */ - public String getPlatform(); - - /* Return the time when this descriptor and the corresponding extra-info - * document was generated. */ - public long getPublishedMillis(); - - /* Return the relay fingerprint, or null if this descriptor does not - * contain a fingerprint line. */ - public String getFingerprint(); - - /* Return whether the relay was hibernating when this descriptor was - * published. */ - public boolean isHibernating(); - - /* Return the number of seconds that this relay has been running, or -1 - * if the descriptor does not contain an uptime line. */ - public int getUptime(); - - /* Return the relay's exit policy consisting of one or more accept or - * reject lines. */ - public List<String> getExitPolicyLines(); - - /* Return the contact information for this relay, or null if no contact - * information is included in the descriptor. */ - public String getContact(); - - /* Return the nicknames or ($-prefixed) fingerprints contained in the - * family line of this relay, or null if the descriptor does not contain - * a family line. */ - public List<String> getFamilyEntries(); - - /* Return the relay's read history. (Current Tor versions include their - * bandwidth histories in their extra-info descriptors, not in their - * server descriptors.) */ - public BandwidthHistory getReadHistory(); - - /* Return the relay's write history. (Current Tor versions include - * their bandwidth histories in their extra-info descriptors, not in - * their server descriptors.) */ - public BandwidthHistory getWriteHistory(); - - /* Return true if the relay uses the enhanced DNS logic, or false if - * doesn't use it or doesn't include an eventdns line in its - * descriptor. */ - public boolean getUsesEnhancedDnsLogic(); - - /* Return whether this relay is a directory cache that provides - * extra-info descriptors. */ - public boolean getCachesExtraInfo(); - - /* Return the digest of the relay's extra-info descriptor, or null if - * the relay did not upload a corresponding extra-info descriptor. */ - public String getExtraInfoDigest(); - - /* Return the hidden service descriptor version(s) that this relay - * stores and serves, or null if it doesn't store and serve any hidden - * service descriptors. */ - public List<Integer> getHiddenServiceDirVersions(); - - /* Return the list of link protocol versions that this relay - * supports. */ - public List<Integer> getLinkProtocolVersions(); - - /* Return the list of circuit protocol versions that this relay - * supports. */ - public List<Integer> getCircuitProtocolVersions(); - - /* Return whether this relay allows single-hop circuits to make exit - * connections. */ - public boolean getAllowSingleHopExits(); -} - diff --git a/src/org/torproject/descriptor/ServerDescriptor.java b/src/org/torproject/descriptor/ServerDescriptor.java new file mode 100644 index 0000000..98a0f02 --- /dev/null +++ b/src/org/torproject/descriptor/ServerDescriptor.java @@ -0,0 +1,110 @@ +/* Copyright 2011, 2012 The Tor Project + * See LICENSE for licensing information */ +package org.torproject.descriptor; + +import java.util.List; + +/* Contains a relay server descriptor. */ +public interface ServerDescriptor extends Descriptor { + + /* Return the relay's nickname. */ + public String getNickname(); + + /* Return the relay's IPv4 address in dotted-quad format. */ + public String getAddress(); + + /* Return the relay's OR port. */ + public int getOrPort(); + + /* Return the relay's SOCKS port which should always be 0. */ + public int getSocksPort(); + + /* Return the relay's directory port. */ + public int getDirPort(); + + /* Return the average bandwidth in bytes per second that the relay is + * willing to sustain over long periods. */ + public int getBandwidthRate(); + + /* Return the burst bandwidth in bytes per second that the relay is + * willing to sustain in very short intervals. */ + public int getBandwidthBurst(); + + /* Return the observed bandwidth in bytes per second as an estimate of + * the capacity that the relay can handle. */ + public int getBandwidthObserved(); + + /* Return the platform string containing the Tor software version and + * the operating system. */ + public String getPlatform(); + + /* Return the time when this descriptor and the corresponding extra-info + * document was generated. */ + public long getPublishedMillis(); + + /* Return the relay fingerprint, or null if this descriptor does not + * contain a fingerprint line. */ + public String getFingerprint(); + + /* Return whether the relay was hibernating when this descriptor was + * published. */ + public boolean isHibernating(); + + /* Return the number of seconds that this relay has been running, or -1 + * if the descriptor does not contain an uptime line. */ + public int getUptime(); + + /* Return the relay's exit policy consisting of one or more accept or + * reject lines. */ + public List<String> getExitPolicyLines(); + + /* Return the contact information for this relay, or null if no contact + * information is included in the descriptor. */ + public String getContact(); + + /* Return the nicknames or ($-prefixed) fingerprints contained in the + * family line of this relay, or null if the descriptor does not contain + * a family line. */ + public List<String> getFamilyEntries(); + + /* Return the relay's read history. (Current Tor versions include their + * bandwidth histories in their extra-info descriptors, not in their + * server descriptors.) */ + public BandwidthHistory getReadHistory(); + + /* Return the relay's write history. (Current Tor versions include + * their bandwidth histories in their extra-info descriptors, not in + * their server descriptors.) */ + public BandwidthHistory getWriteHistory(); + + /* Return true if the relay uses the enhanced DNS logic, or false if + * doesn't use it or doesn't include an eventdns line in its + * descriptor. */ + public boolean getUsesEnhancedDnsLogic(); + + /* Return whether this relay is a directory cache that provides + * extra-info descriptors. */ + public boolean getCachesExtraInfo(); + + /* Return the digest of the relay's extra-info descriptor, or null if + * the relay did not upload a corresponding extra-info descriptor. */ + public String getExtraInfoDigest(); + + /* Return the hidden service descriptor version(s) that this relay + * stores and serves, or null if it doesn't store and serve any hidden + * service descriptors. */ + public List<Integer> getHiddenServiceDirVersions(); + + /* Return the list of link protocol versions that this relay + * supports. */ + public List<Integer> getLinkProtocolVersions(); + + /* Return the list of circuit protocol versions that this relay + * supports. */ + public List<Integer> getCircuitProtocolVersions(); + + /* Return whether this relay allows single-hop circuits to make exit + * connections. */ + public boolean getAllowSingleHopExits(); +} + diff --git a/src/org/torproject/descriptor/impl/DescriptorImpl.java b/src/org/torproject/descriptor/impl/DescriptorImpl.java index 24c1fe9..259a1de 100644 --- a/src/org/torproject/descriptor/impl/DescriptorImpl.java +++ b/src/org/torproject/descriptor/impl/DescriptorImpl.java @@ -37,11 +37,11 @@ public abstract class DescriptorImpl implements Descriptor { } } else if (firstLines.startsWith("router ") || firstLines.contains("\nrouter ")) { - parsedDescriptors.addAll(RelayServerDescriptorImpl. + parsedDescriptors.addAll(ServerDescriptorImpl. parseDescriptors(rawDescriptorBytes)); } else if (firstLines.startsWith("extra-info ") || firstLines.contains("\nextra-info ")) { - parsedDescriptors.addAll(RelayExtraInfoDescriptorImpl. + parsedDescriptors.addAll(ExtraInfoDescriptorImpl. parseDescriptors(rawDescriptorBytes)); } else { throw new DescriptorParseException("Could not detect relay " diff --git a/src/org/torproject/descriptor/impl/ExtraInfoDescriptorImpl.java b/src/org/torproject/descriptor/impl/ExtraInfoDescriptorImpl.java new file mode 100644 index 0000000..6dae9eb --- /dev/null +++ b/src/org/torproject/descriptor/impl/ExtraInfoDescriptorImpl.java @@ -0,0 +1,574 @@ +/* Copyright 2012 The Tor Project + * See LICENSE for licensing information */ +package org.torproject.descriptor.impl; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.SortedMap; +import org.torproject.descriptor.ExtraInfoDescriptor; +import org.torproject.descriptor.BandwidthHistory; + +/* TODO Implement methods to parse the various statistics (other than + * bandwidth histories. */ +/* TODO Write a test class. */ +public class ExtraInfoDescriptorImpl extends DescriptorImpl + implements ExtraInfoDescriptor { + + protected static List<ExtraInfoDescriptor> parseDescriptors( + byte[] descriptorsBytes) { + List<ExtraInfoDescriptor> parsedDescriptors = + new ArrayList<ExtraInfoDescriptor>(); + List<byte[]> splitDescriptorsBytes = + DescriptorImpl.splitRawDescriptorBytes(descriptorsBytes, + "extra-info "); + try { + for (byte[] descriptorBytes : splitDescriptorsBytes) { + ExtraInfoDescriptor parsedDescriptor = + new ExtraInfoDescriptorImpl(descriptorBytes); + parsedDescriptors.add(parsedDescriptor); + } + } catch (DescriptorParseException e) { + /* TODO Handle this error somehow. */ + System.err.println("Failed to parse descriptor. Skipping."); + e.printStackTrace(); + } + return parsedDescriptors; + } + + protected ExtraInfoDescriptorImpl(byte[] descriptorBytes) + throws DescriptorParseException { + super(descriptorBytes); + this.parseDescriptorBytes(); + Set<String> exactlyOnceKeywords = new HashSet<String>(Arrays.asList(( + "extra-info,published,router-signature").split(","))); + this.checkExactlyOnceKeywords(exactlyOnceKeywords); + Set<String> atMostOnceKeywords = new HashSet<String>(Arrays.asList(( + "read-history,write-history,geoip-db-digest,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,dirreq-read-history," + + "dirreq-write-history,entry-stats-end,entry-ips,cell-stats-end," + + "cell-processed-cells,cell-queued-cells,cell-time-in-queue," + + "cell-circuits-per-decile,conn-bi-direct,exit-stats-end," + + "exit-kibibytes-written,exit-kibibytes-read," + + "exit-streams-opened").split(","))); + this.checkAtMostOnceKeywords(atMostOnceKeywords); + /* TODO Add more checks to see that only statistics details lines are + * included with corresponding statistics interval lines. */ + this.checkFirstKeyword("extra-info"); + this.checkLastKeyword("router-signature"); + return; + } + + private void parseDescriptorBytes() throws DescriptorParseException { + try { + BufferedReader br = new BufferedReader(new StringReader( + new String(this.rawDescriptorBytes))); + String line; + boolean skipCrypto = false; + while ((line = br.readLine()) != null) { + String lineNoOpt = line.startsWith("opt ") ? + line.substring("opt ".length()) : line; + String[] partsNoOpt = lineNoOpt.split(" "); + String keyword = partsNoOpt[0]; + if (keyword.equals("extra-info")) { + this.parseExtraInfoLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("published")) { + this.parsePublishedLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("read-history")) { + this.parseReadHistoryLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("write-history")) { + this.parseWriteHistoryLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("geoip-db-digest")) { + this.parseGeoipDbDigestLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("geoip-start-time")) { + this.parseGeoipStartTimeLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("geoip-client-origins")) { + this.parseGeoipClientOriginsLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("dirreq-stats-end")) { + this.parseDirreqStatsEndLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("dirreq-v2-ips")) { + this.parseDirreqV2IpsLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("dirreq-v3-ips")) { + this.parseDirreqV3IpsLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("dirreq-v2-reqs")) { + this.parseDirreqV2ReqsLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("dirreq-v3-reqs")) { + this.parseDirreqV3ReqsLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("dirreq-v2-share")) { + this.parseDirreqV2ShareLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("dirreq-v3-share")) { + this.parseDirreqV3ShareLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("dirreq-v2-resp")) { + this.parseDirreqV2RespLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("dirreq-v3-resp")) { + this.parseDirreqV3RespLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("dirreq-v2-direct-dl")) { + this.parseDirreqV2DirectDlLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("dirreq-v3-direct-dl")) { + this.parseDirreqV3DirectDlLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("dirreq-v2-tunneled-dl")) { + this.parseDirreqV2TunneledDlLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("dirreq-v3-tunneled-dl")) { + this.parseDirreqV3TunneledDlLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("dirreq-read-history")) { + this.parseDirreqReadHistoryLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("dirreq-write-history")) { + this.parseDirreqWriteHistoryLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("entry-stats-end")) { + this.parseEntryStatsEndLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("entry-ips")) { + this.parseEntryIpsLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("cell-stats-end")) { + this.parseCellStatsEndLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("cell-processed-cells")) { + this.parseCellProcessedCellsLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("cell-queued-cells")) { + this.parseCellQueuedCellsLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("cell-time-in-queue")) { + this.parseCellTimeInQueueLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("cell-circuits-per-decile")) { + this.parseCellCircuitsPerDecileLine(line, lineNoOpt, + partsNoOpt); + } else if (keyword.equals("conn-bi-direct")) { + this.parseConnBiDirectLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("exit-stats-end")) { + this.parseExitStatsEndLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("exit-kibibytes-written")) { + this.parseExitKibibytesWrittenLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("exit-kibibytes-read")) { + this.parseExitKibibytesReadLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("exit-streams-opened")) { + this.parseExitStreamsOpenedLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("router-signature")) { + this.parseRouterSignatureLine(line, lineNoOpt, partsNoOpt); + } else if (line.startsWith("-----BEGIN")) { + skipCrypto = true; + } else if (line.startsWith("-----END")) { + skipCrypto = false; + } else if (!skipCrypto) { + /* TODO Is throwing an exception the right thing to do here? + * This is probably fine for development, but once the library + * is in production use, this seems annoying. In theory, + * dir-spec.txt says that unknown lines should be ignored. This + * also applies to the other descriptors. */ + throw new DescriptorParseException("Unrecognized line '" + line + + "'."); + } + } + } catch (IOException e) { + throw new RuntimeException("Internal error: Ran into an " + + "IOException while parsing a String in memory. Something's " + + "really wrong.", e); + } + } + + private void parseExtraInfoLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + if (partsNoOpt.length != 3) { + throw new DescriptorParseException("Illegal line '" + line + + "' in extra-info descriptor."); + } + this.nickname = ParseHelper.parseNickname(line, partsNoOpt[1]); + this.fingerprint = ParseHelper.parseTwentyByteHexString(line, + partsNoOpt[2]); + } + + private void parsePublishedLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + this.publishedMillis = ParseHelper.parseTimestampAtIndex(line, + partsNoOpt, 1, 2); + } + + private void parseReadHistoryLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + this.readHistory = new BandwidthHistoryImpl(line, lineNoOpt, + partsNoOpt); + } + + private void parseWriteHistoryLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + this.writeHistory = new BandwidthHistoryImpl(line, lineNoOpt, + partsNoOpt); + } + + private void parseGeoipDbDigestLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseGeoipStartTimeLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseGeoipClientOriginsLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseDirreqStatsEndLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseDirreqV2IpsLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseDirreqV3IpsLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseDirreqV2ReqsLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseDirreqV3ReqsLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseDirreqV2ShareLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseDirreqV3ShareLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseDirreqV2RespLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseDirreqV3RespLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseDirreqV2DirectDlLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseDirreqV3DirectDlLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseDirreqV2TunneledDlLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseDirreqV3TunneledDlLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseDirreqReadHistoryLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + this.dirreqReadHistory = new BandwidthHistoryImpl(line, lineNoOpt, + partsNoOpt); + } + + private void parseDirreqWriteHistoryLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + this.dirreqWriteHistory = new BandwidthHistoryImpl(line, lineNoOpt, + partsNoOpt); + } + + private void parseEntryStatsEndLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseEntryIpsLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseCellStatsEndLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseCellProcessedCellsLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseCellQueuedCellsLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseCellTimeInQueueLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseCellCircuitsPerDecileLine(String line, + String lineNoOpt, String[] partsNoOpt) + throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseConnBiDirectLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseExitStatsEndLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseExitKibibytesWrittenLine(String line, + String lineNoOpt, String[] partsNoOpt) + throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseExitKibibytesReadLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseExitStreamsOpenedLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* TODO Implement me. */ + } + + private void parseRouterSignatureLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + if (!lineNoOpt.equals("router-signature")) { + throw new DescriptorParseException("Illegal line '" + line + "'."); + } + /* Not parsing crypto parts (yet). */ + } + + private String nickname; + public String getNickname() { + return this.nickname; + } + + private String fingerprint; + public String getFingerprint() { + return this.fingerprint; + } + + private long publishedMillis; + public long getPublishedMillis() { + return this.publishedMillis; + } + + private BandwidthHistory readHistory; + public BandwidthHistory getReadHistory() { + return this.readHistory; + } + + private BandwidthHistory writeHistory; + public BandwidthHistory getWriteHistory() { + return this.writeHistory; + } + + public String getGeoipDbDigest() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public long getDirreqStatsEndMillis() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public long getDirreqStatsIntervalLength() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public SortedMap<String, Integer> getDirreqV2Ips() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public SortedMap<String, Integer> getDirreqV3Ips() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public SortedMap<String, Integer> getDirreqV2Reqs() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public SortedMap<String, Integer> getDirreqV3Reqs() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public double getDirreqV2Share() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public double getDirreqV3Share() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public SortedMap<String, Integer> getDirreqV2Resp() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public SortedMap<String, Integer> getDirreqV3Resp() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public SortedMap<String, Integer> getDirreqV2DirectDl() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public SortedMap<String, Integer> getDirreqV3DirectDl() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public SortedMap<String, Integer> getDirreqV2TunneledDl() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public SortedMap<String, Integer> getDirreqV3TunneledDl() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + private BandwidthHistory dirreqReadHistory; + public BandwidthHistory getDirreqReadHistory() { + return this.dirreqReadHistory; + } + + private BandwidthHistory dirreqWriteHistory; + public BandwidthHistory getDirreqWriteHistory() { + return this.dirreqWriteHistory; + } + + public long getEntryStatsEndMillis() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public long getEntryStatsIntervalLength() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public SortedMap<String, Integer> getEntryIps() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public long getCellStatsEndMillis() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public long getCellStatsIntervalLength() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public List<Integer> getCellProcessedCells() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public List<Integer> getCellQueueCells() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public List<Integer> getCellTimeInQueue() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public int getCellCircuitsPerDecile() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public long getConnBiDirectStatsEndMillis() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public long getConnBiDirectIntervalLength() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public int getConnBiDirectBelow() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public int getConnBiDirectRead() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public int getConnBiDirectWrite() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public int getConnBiDirectBoth() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public long getExitStatsEndMillis() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public long getExitStatsIntervalLength() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public SortedMap<Integer, Integer> getExitKibibytesWritten() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public SortedMap<Integer, Integer> getExitKibibytesRead() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } + + public SortedMap<Integer, Integer> getExitStreamsOpened() { + /* TODO Implement me. */ + throw new UnsupportedOperationException(); + } +} + diff --git a/src/org/torproject/descriptor/impl/RelayExtraInfoDescriptorImpl.java b/src/org/torproject/descriptor/impl/RelayExtraInfoDescriptorImpl.java deleted file mode 100644 index a07caec..0000000 --- a/src/org/torproject/descriptor/impl/RelayExtraInfoDescriptorImpl.java +++ /dev/null @@ -1,574 +0,0 @@ -/* Copyright 2012 The Tor Project - * See LICENSE for licensing information */ -package org.torproject.descriptor.impl; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.SortedMap; -import org.torproject.descriptor.RelayExtraInfoDescriptor; -import org.torproject.descriptor.BandwidthHistory; - -/* TODO Implement methods to parse the various statistics (other than - * bandwidth histories. */ -/* TODO Write a test class. */ -public class RelayExtraInfoDescriptorImpl extends DescriptorImpl - implements RelayExtraInfoDescriptor { - - protected static List<RelayExtraInfoDescriptor> parseDescriptors( - byte[] descriptorsBytes) { - List<RelayExtraInfoDescriptor> parsedDescriptors = - new ArrayList<RelayExtraInfoDescriptor>(); - List<byte[]> splitDescriptorsBytes = - DescriptorImpl.splitRawDescriptorBytes(descriptorsBytes, - "extra-info "); - try { - for (byte[] descriptorBytes : splitDescriptorsBytes) { - RelayExtraInfoDescriptor parsedDescriptor = - new RelayExtraInfoDescriptorImpl(descriptorBytes); - parsedDescriptors.add(parsedDescriptor); - } - } catch (DescriptorParseException e) { - /* TODO Handle this error somehow. */ - System.err.println("Failed to parse descriptor. Skipping."); - e.printStackTrace(); - } - return parsedDescriptors; - } - - protected RelayExtraInfoDescriptorImpl(byte[] descriptorBytes) - throws DescriptorParseException { - super(descriptorBytes); - this.parseDescriptorBytes(); - Set<String> exactlyOnceKeywords = new HashSet<String>(Arrays.asList(( - "extra-info,published,router-signature").split(","))); - this.checkExactlyOnceKeywords(exactlyOnceKeywords); - Set<String> atMostOnceKeywords = new HashSet<String>(Arrays.asList(( - "read-history,write-history,geoip-db-digest,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,dirreq-read-history," - + "dirreq-write-history,entry-stats-end,entry-ips,cell-stats-end," - + "cell-processed-cells,cell-queued-cells,cell-time-in-queue," - + "cell-circuits-per-decile,conn-bi-direct,exit-stats-end," - + "exit-kibibytes-written,exit-kibibytes-read," - + "exit-streams-opened").split(","))); - this.checkAtMostOnceKeywords(atMostOnceKeywords); - /* TODO Add more checks to see that only statistics details lines are - * included with corresponding statistics interval lines. */ - this.checkFirstKeyword("extra-info"); - this.checkLastKeyword("router-signature"); - return; - } - - private void parseDescriptorBytes() throws DescriptorParseException { - try { - BufferedReader br = new BufferedReader(new StringReader( - new String(this.rawDescriptorBytes))); - String line; - boolean skipCrypto = false; - while ((line = br.readLine()) != null) { - String lineNoOpt = line.startsWith("opt ") ? - line.substring("opt ".length()) : line; - String[] partsNoOpt = lineNoOpt.split(" "); - String keyword = partsNoOpt[0]; - if (keyword.equals("extra-info")) { - this.parseExtraInfoLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("published")) { - this.parsePublishedLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("read-history")) { - this.parseReadHistoryLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("write-history")) { - this.parseWriteHistoryLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("geoip-db-digest")) { - this.parseGeoipDbDigestLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("geoip-start-time")) { - this.parseGeoipStartTimeLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("geoip-client-origins")) { - this.parseGeoipClientOriginsLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("dirreq-stats-end")) { - this.parseDirreqStatsEndLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("dirreq-v2-ips")) { - this.parseDirreqV2IpsLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("dirreq-v3-ips")) { - this.parseDirreqV3IpsLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("dirreq-v2-reqs")) { - this.parseDirreqV2ReqsLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("dirreq-v3-reqs")) { - this.parseDirreqV3ReqsLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("dirreq-v2-share")) { - this.parseDirreqV2ShareLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("dirreq-v3-share")) { - this.parseDirreqV3ShareLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("dirreq-v2-resp")) { - this.parseDirreqV2RespLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("dirreq-v3-resp")) { - this.parseDirreqV3RespLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("dirreq-v2-direct-dl")) { - this.parseDirreqV2DirectDlLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("dirreq-v3-direct-dl")) { - this.parseDirreqV3DirectDlLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("dirreq-v2-tunneled-dl")) { - this.parseDirreqV2TunneledDlLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("dirreq-v3-tunneled-dl")) { - this.parseDirreqV3TunneledDlLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("dirreq-read-history")) { - this.parseDirreqReadHistoryLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("dirreq-write-history")) { - this.parseDirreqWriteHistoryLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("entry-stats-end")) { - this.parseEntryStatsEndLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("entry-ips")) { - this.parseEntryIpsLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("cell-stats-end")) { - this.parseCellStatsEndLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("cell-processed-cells")) { - this.parseCellProcessedCellsLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("cell-queued-cells")) { - this.parseCellQueuedCellsLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("cell-time-in-queue")) { - this.parseCellTimeInQueueLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("cell-circuits-per-decile")) { - this.parseCellCircuitsPerDecileLine(line, lineNoOpt, - partsNoOpt); - } else if (keyword.equals("conn-bi-direct")) { - this.parseConnBiDirectLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("exit-stats-end")) { - this.parseExitStatsEndLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("exit-kibibytes-written")) { - this.parseExitKibibytesWrittenLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("exit-kibibytes-read")) { - this.parseExitKibibytesReadLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("exit-streams-opened")) { - this.parseExitStreamsOpenedLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("router-signature")) { - this.parseRouterSignatureLine(line, lineNoOpt, partsNoOpt); - } else if (line.startsWith("-----BEGIN")) { - skipCrypto = true; - } else if (line.startsWith("-----END")) { - skipCrypto = false; - } else if (!skipCrypto) { - /* TODO Is throwing an exception the right thing to do here? - * This is probably fine for development, but once the library - * is in production use, this seems annoying. In theory, - * dir-spec.txt says that unknown lines should be ignored. This - * also applies to the other descriptors. */ - throw new DescriptorParseException("Unrecognized line '" + line - + "'."); - } - } - } catch (IOException e) { - throw new RuntimeException("Internal error: Ran into an " - + "IOException while parsing a String in memory. Something's " - + "really wrong.", e); - } - } - - private void parseExtraInfoLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - if (partsNoOpt.length != 3) { - throw new DescriptorParseException("Illegal line '" + line - + "' in extra-info descriptor."); - } - this.nickname = ParseHelper.parseNickname(line, partsNoOpt[1]); - this.fingerprint = ParseHelper.parseTwentyByteHexString(line, - partsNoOpt[2]); - } - - private void parsePublishedLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - this.publishedMillis = ParseHelper.parseTimestampAtIndex(line, - partsNoOpt, 1, 2); - } - - private void parseReadHistoryLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - this.readHistory = new BandwidthHistoryImpl(line, lineNoOpt, - partsNoOpt); - } - - private void parseWriteHistoryLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - this.writeHistory = new BandwidthHistoryImpl(line, lineNoOpt, - partsNoOpt); - } - - private void parseGeoipDbDigestLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseGeoipStartTimeLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseGeoipClientOriginsLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseDirreqStatsEndLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseDirreqV2IpsLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseDirreqV3IpsLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseDirreqV2ReqsLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseDirreqV3ReqsLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseDirreqV2ShareLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseDirreqV3ShareLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseDirreqV2RespLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseDirreqV3RespLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseDirreqV2DirectDlLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseDirreqV3DirectDlLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseDirreqV2TunneledDlLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseDirreqV3TunneledDlLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseDirreqReadHistoryLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - this.dirreqReadHistory = new BandwidthHistoryImpl(line, lineNoOpt, - partsNoOpt); - } - - private void parseDirreqWriteHistoryLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - this.dirreqWriteHistory = new BandwidthHistoryImpl(line, lineNoOpt, - partsNoOpt); - } - - private void parseEntryStatsEndLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseEntryIpsLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseCellStatsEndLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseCellProcessedCellsLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseCellQueuedCellsLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseCellTimeInQueueLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseCellCircuitsPerDecileLine(String line, - String lineNoOpt, String[] partsNoOpt) - throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseConnBiDirectLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseExitStatsEndLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseExitKibibytesWrittenLine(String line, - String lineNoOpt, String[] partsNoOpt) - throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseExitKibibytesReadLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseExitStreamsOpenedLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* TODO Implement me. */ - } - - private void parseRouterSignatureLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - if (!lineNoOpt.equals("router-signature")) { - throw new DescriptorParseException("Illegal line '" + line + "'."); - } - /* Not parsing crypto parts (yet). */ - } - - private String nickname; - public String getNickname() { - return this.nickname; - } - - private String fingerprint; - public String getFingerprint() { - return this.fingerprint; - } - - private long publishedMillis; - public long getPublishedMillis() { - return this.publishedMillis; - } - - private BandwidthHistory readHistory; - public BandwidthHistory getReadHistory() { - return this.readHistory; - } - - private BandwidthHistory writeHistory; - public BandwidthHistory getWriteHistory() { - return this.writeHistory; - } - - public String getGeoipDbDigest() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public long getDirreqStatsEndMillis() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public long getDirreqStatsIntervalLength() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public SortedMap<String, Integer> getDirreqV2Ips() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public SortedMap<String, Integer> getDirreqV3Ips() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public SortedMap<String, Integer> getDirreqV2Reqs() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public SortedMap<String, Integer> getDirreqV3Reqs() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public double getDirreqV2Share() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public double getDirreqV3Share() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public SortedMap<String, Integer> getDirreqV2Resp() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public SortedMap<String, Integer> getDirreqV3Resp() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public SortedMap<String, Integer> getDirreqV2DirectDl() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public SortedMap<String, Integer> getDirreqV3DirectDl() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public SortedMap<String, Integer> getDirreqV2TunneledDl() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public SortedMap<String, Integer> getDirreqV3TunneledDl() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - private BandwidthHistory dirreqReadHistory; - public BandwidthHistory getDirreqReadHistory() { - return this.dirreqReadHistory; - } - - private BandwidthHistory dirreqWriteHistory; - public BandwidthHistory getDirreqWriteHistory() { - return this.dirreqWriteHistory; - } - - public long getEntryStatsEndMillis() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public long getEntryStatsIntervalLength() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public SortedMap<String, Integer> getEntryIps() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public long getCellStatsEndMillis() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public long getCellStatsIntervalLength() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public List<Integer> getCellProcessedCells() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public List<Integer> getCellQueueCells() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public List<Integer> getCellTimeInQueue() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public int getCellCircuitsPerDecile() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public long getConnBiDirectStatsEndMillis() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public long getConnBiDirectIntervalLength() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public int getConnBiDirectBelow() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public int getConnBiDirectRead() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public int getConnBiDirectWrite() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public int getConnBiDirectBoth() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public long getExitStatsEndMillis() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public long getExitStatsIntervalLength() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public SortedMap<Integer, Integer> getExitKibibytesWritten() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public SortedMap<Integer, Integer> getExitKibibytesRead() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } - - public SortedMap<Integer, Integer> getExitStreamsOpened() { - /* TODO Implement me. */ - throw new UnsupportedOperationException(); - } -} - diff --git a/src/org/torproject/descriptor/impl/RelayServerDescriptorImpl.java b/src/org/torproject/descriptor/impl/RelayServerDescriptorImpl.java deleted file mode 100644 index 472a2bc..0000000 --- a/src/org/torproject/descriptor/impl/RelayServerDescriptorImpl.java +++ /dev/null @@ -1,532 +0,0 @@ -/* Copyright 2012 The Tor Project - * See LICENSE for licensing information */ -package org.torproject.descriptor.impl; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import org.torproject.descriptor.RelayServerDescriptor; -import org.torproject.descriptor.BandwidthHistory; - -/* Contains a relay server descriptor. */ -public class RelayServerDescriptorImpl extends DescriptorImpl - implements RelayServerDescriptor { - - protected static List<RelayServerDescriptor> parseDescriptors( - byte[] descriptorsBytes) { - List<RelayServerDescriptor> parsedDescriptors = - new ArrayList<RelayServerDescriptor>(); - List<byte[]> splitDescriptorsBytes = - DescriptorImpl.splitRawDescriptorBytes(descriptorsBytes, - "router "); - try { - for (byte[] descriptorBytes : splitDescriptorsBytes) { - RelayServerDescriptor parsedDescriptor = - new RelayServerDescriptorImpl(descriptorBytes); - parsedDescriptors.add(parsedDescriptor); - } - } catch (DescriptorParseException e) { - /* TODO Handle this error somehow. */ - System.err.println("Failed to parse descriptor. Skipping."); - e.printStackTrace(); - } - return parsedDescriptors; - } - - protected RelayServerDescriptorImpl(byte[] descriptorBytes) - throws DescriptorParseException { - super(descriptorBytes); - this.parseDescriptorBytes(); - Set<String> exactlyOnceKeywords = new HashSet<String>(Arrays.asList(( - "router,bandwidth,published,onion-key,signing-key," - + "router-signature").split(","))); - this.checkExactlyOnceKeywords(exactlyOnceKeywords); - Set<String> atMostOnceKeywords = new HashSet<String>(Arrays.asList(( - "platform,fingerprint,hibernating,uptime,contact,family," - + "read-history,write-history,eventdns,caches-extra-info," - + "extra-info-digest,hidden-service-dir,protocols," - + "allow-single-hop-exits").split(","))); - this.checkAtMostOnceKeywords(atMostOnceKeywords); - this.checkFirstKeyword("router"); - this.checkLastKeyword("router-signature"); - if (this.getKeywordCount("accept") == 0 && - this.getKeywordCount("reject") == 0) { - throw new DescriptorParseException("Either keyword 'accept' or " - + "'reject' must be contained at least once."); - } - return; - } - - private void parseDescriptorBytes() throws DescriptorParseException { - try { - BufferedReader br = new BufferedReader(new StringReader( - new String(this.rawDescriptorBytes))); - String line; - boolean skipCrypto = false; - while ((line = br.readLine()) != null) { - if (line.startsWith("@")) { - continue; - } - String lineNoOpt = line.startsWith("opt ") ? - line.substring("opt ".length()) : line; - String[] partsNoOpt = lineNoOpt.split(" "); - String keyword = partsNoOpt[0]; - if (keyword.equals("router")) { - this.parseRouterLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("bandwidth")) { - this.parseBandwidthLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("platform")) { - this.parsePlatformLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("published")) { - this.parsePublishedLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("fingerprint")) { - this.parseFingerprintLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("hibernating")) { - this.parseHibernatingLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("uptime")) { - this.parseUptimeLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("onion-key")) { - this.parseOnionKeyLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("signing-key")) { - this.parseSigningKeyLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("accept")) { - this.parseAcceptLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("reject")) { - this.parseRejectLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("router-signature")) { - this.parseRouterSignatureLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("contact")) { - this.parseContactLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("family")) { - this.parseFamilyLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("read-history")) { - this.parseReadHistoryLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("write-history")) { - this.parseWriteHistoryLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("eventdns")) { - this.parseEventdnsLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("caches-extra-info")) { - this.parseCachesExtraInfoLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("extra-info-digest")) { - this.parseExtraInfoDigestLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("hidden-service-dir")) { - this.parseHiddenServiceDirLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("protocols")) { - this.parseProtocolsLine(line, lineNoOpt, partsNoOpt); - } else if (keyword.equals("allow-single-hop-exits")) { - this.parseAllowSingleHopExitsLine(line, lineNoOpt, partsNoOpt); - } else if (line.startsWith("-----BEGIN")) { - skipCrypto = true; - } else if (line.startsWith("-----END")) { - skipCrypto = false; - } else if (!skipCrypto) { - /* TODO Is throwing an exception the right thing to do here? - * This is probably fine for development, but once the library - * is in production use, this seems annoying. In theory, - * dir-spec.txt says that unknown lines should be ignored. This - * also applies to the other descriptors. */ - throw new DescriptorParseException("Unrecognized line '" + line - + "'."); - } - } - } catch (IOException e) { - throw new RuntimeException("Internal error: Ran into an " - + "IOException while parsing a String in memory. Something's " - + "really wrong.", e); - } - } - - private void parseRouterLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - if (partsNoOpt.length != 6) { - throw new DescriptorParseException("Illegal line '" + line - + "' in server descriptor."); - } - this.nickname = ParseHelper.parseNickname(line, partsNoOpt[1]); - this.address = ParseHelper.parseIpv4Address(line, partsNoOpt[2]); - this.orPort = ParseHelper.parsePort(line, partsNoOpt[3]); - this.socksPort = ParseHelper.parsePort(line, partsNoOpt[4]); - this.dirPort = ParseHelper.parsePort(line, partsNoOpt[5]); - } - - private void parseBandwidthLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - if (partsNoOpt.length != 4) { - throw new DescriptorParseException("Wrong number of values in line " - + "'" + line + "'."); - } - boolean isValid = false; - try { - this.bandwidthRate = Integer.parseInt(partsNoOpt[1]); - this.bandwidthBurst = Integer.parseInt(partsNoOpt[2]); - this.bandwidthObserved = Integer.parseInt(partsNoOpt[3]); - if (this.bandwidthRate >= 0 && this.bandwidthBurst >= 0 && - this.bandwidthObserved >= 0) { - isValid = true; - } - } catch (NumberFormatException e) { - /* Handle below. */ - } - if (!isValid) { - throw new DescriptorParseException("Illegal values in line '" + line - + "'."); - } - } - - private void parsePlatformLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - if (lineNoOpt.length() > "platform ".length()) { - this.platform = lineNoOpt.substring("platform ".length()); - } else { - this.platform = ""; - } - } - - private void parsePublishedLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - this.publishedMillis = ParseHelper.parseTimestampAtIndex(line, - partsNoOpt, 1, 2); - } - - private void parseFingerprintLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - if (lineNoOpt.length() != "fingerprint".length() + 5 * 10) { - throw new DescriptorParseException("Illegal line '" + line + "'."); - } - this.fingerprint = ParseHelper.parseTwentyByteHexString(line, - lineNoOpt.substring("fingerprint ".length()).replaceAll(" ", "")); - } - - private void parseHibernatingLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - if (partsNoOpt.length != 2) { - throw new DescriptorParseException("Illegal line '" + line + "'."); - } - if (partsNoOpt[1].equals("1")) { - this.hibernating = true; - } else if (partsNoOpt[1].equals("0")) { - this.hibernating = false; - } else { - throw new DescriptorParseException("Illegal line '" + line + "'."); - } - } - - private void parseUptimeLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - if (partsNoOpt.length != 2) { - throw new DescriptorParseException("Wrong number of values in line " - + "'" + line + "'."); - } - boolean isValid = false; - try { - this.uptime = Integer.parseInt(partsNoOpt[1]); - if (this.uptime >= 0) { - isValid = true; - } - } catch (NumberFormatException e) { - /* Handle below. */ - } - if (!isValid) { - throw new DescriptorParseException("Illegal value in line '" + line - + "'."); - } - } - - private void parseOnionKeyLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* Not parsing crypto parts (yet). */ - } - - private void parseSigningKeyLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - /* Not parsing crypto parts (yet). */ - } - - private void parseAcceptLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - this.parseExitPolicyLine(line, lineNoOpt, partsNoOpt); - } - - private void parseRejectLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - this.parseExitPolicyLine(line, lineNoOpt, partsNoOpt); - } - - private void parseExitPolicyLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - if (partsNoOpt.length != 2) { - throw new DescriptorParseException("Illegal line '" + line + "'."); - } - ParseHelper.parseExitPattern(line, partsNoOpt[1]); - this.exitPolicyLines.add(lineNoOpt); - } - - private void parseRouterSignatureLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - if (!lineNoOpt.equals("router-signature")) { - throw new DescriptorParseException("Illegal line '" + line + "'."); - } - /* Not parsing crypto parts (yet). */ - } - - private void parseContactLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - if (lineNoOpt.length() > "contact ".length()) { - this.contact = lineNoOpt.substring("contact ".length()); - } else { - this.contact = ""; - } - } - - private void parseFamilyLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - this.familyEntries = new ArrayList<String>(); - for (int i = 1; i < partsNoOpt.length; i++) { - if (partsNoOpt[i].startsWith("$")) { - this.familyEntries.add("$" - + ParseHelper.parseTwentyByteHexString(line, - partsNoOpt[i].substring(1))); - } else { - this.familyEntries.add(ParseHelper.parseNickname(line, - partsNoOpt[i])); - } - } - } - - private void parseReadHistoryLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - this.readHistory = new BandwidthHistoryImpl(line, lineNoOpt, - partsNoOpt); - } - - private void parseWriteHistoryLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - this.writeHistory = new BandwidthHistoryImpl(line, lineNoOpt, - partsNoOpt); - } - - private void parseEventdnsLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - if (partsNoOpt.length != 2) { - throw new DescriptorParseException("Illegal line '" + line + "'."); - } - if (partsNoOpt[1].equals("true")) { - this.usesEnhancedDnsLogic = true; - } else if (partsNoOpt[1].equals("false")) { - this.usesEnhancedDnsLogic = false; - } else { - throw new DescriptorParseException("Illegal line '" + line + "'."); - } - } - - private void parseCachesExtraInfoLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - if (!lineNoOpt.equals("caches-extra-info")) { - throw new DescriptorParseException("Illegal line '" + line + "'."); - } - this.cachesExtraInfo = true; - } - - private void parseExtraInfoDigestLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - if (partsNoOpt.length != 2) { - throw new DescriptorParseException("Illegal line '" + line + "'."); - } - this.extraInfoDigest = ParseHelper.parseTwentyByteHexString(line, - partsNoOpt[1]); - } - - private void parseHiddenServiceDirLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - this.hiddenServiceDirVersions = new ArrayList<Integer>(); - if (partsNoOpt.length == 1) { - this.hiddenServiceDirVersions.add(2); - } else { - try { - for (int i = 1; i < partsNoOpt.length; i++) { - this.hiddenServiceDirVersions.add(Integer.parseInt( - partsNoOpt[i])); - } - } catch (NumberFormatException e) { - throw new DescriptorParseException("Illegal value in line '" - + line + "'."); - } - } - } - - private void parseProtocolsLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - List<String> partsList = Arrays.asList(partsNoOpt); - boolean isValid = true; - this.linkProtocolVersions = new ArrayList<Integer>(); - this.circuitProtocolVersions = new ArrayList<Integer>(); - List<Integer> protocolVersions = null; - for (int i = 1; i < partsNoOpt.length; i++) { - String part = partsNoOpt[i]; - if (part.equals("Link")) { - protocolVersions = this.linkProtocolVersions; - } else if (part.equals("Circuit")) { - protocolVersions = this.circuitProtocolVersions; - } else if (protocolVersions == null) { - isValid = false; - break; - } else { - try { - protocolVersions.add(Integer.parseInt(part)); - } catch (NumberFormatException e) { - isValid = false; - break; - } - } - } - if (protocolVersions != this.circuitProtocolVersions) { - isValid = false; - } - if (!isValid) { - throw new DescriptorParseException("Illegal line '" + line + "'."); - } - } - - private void parseAllowSingleHopExitsLine(String line, String lineNoOpt, - String[] partsNoOpt) throws DescriptorParseException { - if (!lineNoOpt.equals("allow-single-hop-exits")) { - throw new DescriptorParseException("Illegal line '" + line + "'."); - } - this.allowSingleHopExits = true; - } - - private String nickname; - public String getNickname() { - return this.nickname; - } - - private String address; - public String getAddress() { - return this.address; - } - - private int orPort; - public int getOrPort() { - return this.orPort; - } - - private int socksPort; - public int getSocksPort() { - return this.socksPort; - } - - private int dirPort; - public int getDirPort() { - return this.dirPort; - } - - private int bandwidthRate; - public int getBandwidthRate() { - return this.bandwidthRate; - } - - private int bandwidthBurst; - public int getBandwidthBurst() { - return this.bandwidthBurst; - } - - private int bandwidthObserved; - public int getBandwidthObserved() { - return this.bandwidthObserved; - } - - private String platform; - public String getPlatform() { - return this.platform; - } - - private long publishedMillis; - public long getPublishedMillis() { - return this.publishedMillis; - } - - private String fingerprint; - public String getFingerprint() { - return this.fingerprint; - } - - private boolean hibernating; - public boolean isHibernating() { - return this.hibernating; - } - - private int uptime = -1; - public int getUptime() { - return this.uptime; - } - - private List<String> exitPolicyLines = new ArrayList<String>(); - public List<String> getExitPolicyLines() { - return new ArrayList<String>(this.exitPolicyLines); - } - - private String contact; - public String getContact() { - return this.contact; - } - - private List<String> familyEntries; - public List<String> getFamilyEntries() { - return this.familyEntries == null ? null : - new ArrayList<String>(this.familyEntries); - } - - private BandwidthHistory readHistory; - public BandwidthHistory getReadHistory() { - return this.readHistory; - } - - private BandwidthHistory writeHistory; - public BandwidthHistory getWriteHistory() { - return this.writeHistory; - } - - private boolean usesEnhancedDnsLogic; - public boolean getUsesEnhancedDnsLogic() { - return this.usesEnhancedDnsLogic; - } - - private boolean cachesExtraInfo; - public boolean getCachesExtraInfo() { - return this.cachesExtraInfo; - } - - private String extraInfoDigest; - public String getExtraInfoDigest() { - return this.extraInfoDigest; - } - - private List<Integer> hiddenServiceDirVersions; - public List<Integer> getHiddenServiceDirVersions() { - return this.hiddenServiceDirVersions == null ? null : - new ArrayList<Integer>(this.hiddenServiceDirVersions); - } - - private List<Integer> linkProtocolVersions; - public List<Integer> getLinkProtocolVersions() { - return this.linkProtocolVersions == null ? null : - new ArrayList<Integer>(this.linkProtocolVersions); - } - - private List<Integer> circuitProtocolVersions; - public List<Integer> getCircuitProtocolVersions() { - return this.circuitProtocolVersions == null ? null : - new ArrayList<Integer>(this.circuitProtocolVersions); - } - - private boolean allowSingleHopExits; - public boolean getAllowSingleHopExits() { - return this.allowSingleHopExits; - } -} - diff --git a/src/org/torproject/descriptor/impl/ServerDescriptorImpl.java b/src/org/torproject/descriptor/impl/ServerDescriptorImpl.java new file mode 100644 index 0000000..878955e --- /dev/null +++ b/src/org/torproject/descriptor/impl/ServerDescriptorImpl.java @@ -0,0 +1,532 @@ +/* Copyright 2012 The Tor Project + * See LICENSE for licensing information */ +package org.torproject.descriptor.impl; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.torproject.descriptor.ServerDescriptor; +import org.torproject.descriptor.BandwidthHistory; + +/* Contains a relay server descriptor. */ +public class ServerDescriptorImpl extends DescriptorImpl + implements ServerDescriptor { + + protected static List<ServerDescriptor> parseDescriptors( + byte[] descriptorsBytes) { + List<ServerDescriptor> parsedDescriptors = + new ArrayList<ServerDescriptor>(); + List<byte[]> splitDescriptorsBytes = + DescriptorImpl.splitRawDescriptorBytes(descriptorsBytes, + "router "); + try { + for (byte[] descriptorBytes : splitDescriptorsBytes) { + ServerDescriptor parsedDescriptor = + new ServerDescriptorImpl(descriptorBytes); + parsedDescriptors.add(parsedDescriptor); + } + } catch (DescriptorParseException e) { + /* TODO Handle this error somehow. */ + System.err.println("Failed to parse descriptor. Skipping."); + e.printStackTrace(); + } + return parsedDescriptors; + } + + protected ServerDescriptorImpl(byte[] descriptorBytes) + throws DescriptorParseException { + super(descriptorBytes); + this.parseDescriptorBytes(); + Set<String> exactlyOnceKeywords = new HashSet<String>(Arrays.asList(( + "router,bandwidth,published,onion-key,signing-key," + + "router-signature").split(","))); + this.checkExactlyOnceKeywords(exactlyOnceKeywords); + Set<String> atMostOnceKeywords = new HashSet<String>(Arrays.asList(( + "platform,fingerprint,hibernating,uptime,contact,family," + + "read-history,write-history,eventdns,caches-extra-info," + + "extra-info-digest,hidden-service-dir,protocols," + + "allow-single-hop-exits").split(","))); + this.checkAtMostOnceKeywords(atMostOnceKeywords); + this.checkFirstKeyword("router"); + this.checkLastKeyword("router-signature"); + if (this.getKeywordCount("accept") == 0 && + this.getKeywordCount("reject") == 0) { + throw new DescriptorParseException("Either keyword 'accept' or " + + "'reject' must be contained at least once."); + } + return; + } + + private void parseDescriptorBytes() throws DescriptorParseException { + try { + BufferedReader br = new BufferedReader(new StringReader( + new String(this.rawDescriptorBytes))); + String line; + boolean skipCrypto = false; + while ((line = br.readLine()) != null) { + if (line.startsWith("@")) { + continue; + } + String lineNoOpt = line.startsWith("opt ") ? + line.substring("opt ".length()) : line; + String[] partsNoOpt = lineNoOpt.split(" "); + String keyword = partsNoOpt[0]; + if (keyword.equals("router")) { + this.parseRouterLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("bandwidth")) { + this.parseBandwidthLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("platform")) { + this.parsePlatformLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("published")) { + this.parsePublishedLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("fingerprint")) { + this.parseFingerprintLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("hibernating")) { + this.parseHibernatingLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("uptime")) { + this.parseUptimeLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("onion-key")) { + this.parseOnionKeyLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("signing-key")) { + this.parseSigningKeyLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("accept")) { + this.parseAcceptLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("reject")) { + this.parseRejectLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("router-signature")) { + this.parseRouterSignatureLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("contact")) { + this.parseContactLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("family")) { + this.parseFamilyLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("read-history")) { + this.parseReadHistoryLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("write-history")) { + this.parseWriteHistoryLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("eventdns")) { + this.parseEventdnsLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("caches-extra-info")) { + this.parseCachesExtraInfoLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("extra-info-digest")) { + this.parseExtraInfoDigestLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("hidden-service-dir")) { + this.parseHiddenServiceDirLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("protocols")) { + this.parseProtocolsLine(line, lineNoOpt, partsNoOpt); + } else if (keyword.equals("allow-single-hop-exits")) { + this.parseAllowSingleHopExitsLine(line, lineNoOpt, partsNoOpt); + } else if (line.startsWith("-----BEGIN")) { + skipCrypto = true; + } else if (line.startsWith("-----END")) { + skipCrypto = false; + } else if (!skipCrypto) { + /* TODO Is throwing an exception the right thing to do here? + * This is probably fine for development, but once the library + * is in production use, this seems annoying. In theory, + * dir-spec.txt says that unknown lines should be ignored. This + * also applies to the other descriptors. */ + throw new DescriptorParseException("Unrecognized line '" + line + + "'."); + } + } + } catch (IOException e) { + throw new RuntimeException("Internal error: Ran into an " + + "IOException while parsing a String in memory. Something's " + + "really wrong.", e); + } + } + + private void parseRouterLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + if (partsNoOpt.length != 6) { + throw new DescriptorParseException("Illegal line '" + line + + "' in server descriptor."); + } + this.nickname = ParseHelper.parseNickname(line, partsNoOpt[1]); + this.address = ParseHelper.parseIpv4Address(line, partsNoOpt[2]); + this.orPort = ParseHelper.parsePort(line, partsNoOpt[3]); + this.socksPort = ParseHelper.parsePort(line, partsNoOpt[4]); + this.dirPort = ParseHelper.parsePort(line, partsNoOpt[5]); + } + + private void parseBandwidthLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + if (partsNoOpt.length != 4) { + throw new DescriptorParseException("Wrong number of values in line " + + "'" + line + "'."); + } + boolean isValid = false; + try { + this.bandwidthRate = Integer.parseInt(partsNoOpt[1]); + this.bandwidthBurst = Integer.parseInt(partsNoOpt[2]); + this.bandwidthObserved = Integer.parseInt(partsNoOpt[3]); + if (this.bandwidthRate >= 0 && this.bandwidthBurst >= 0 && + this.bandwidthObserved >= 0) { + isValid = true; + } + } catch (NumberFormatException e) { + /* Handle below. */ + } + if (!isValid) { + throw new DescriptorParseException("Illegal values in line '" + line + + "'."); + } + } + + private void parsePlatformLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + if (lineNoOpt.length() > "platform ".length()) { + this.platform = lineNoOpt.substring("platform ".length()); + } else { + this.platform = ""; + } + } + + private void parsePublishedLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + this.publishedMillis = ParseHelper.parseTimestampAtIndex(line, + partsNoOpt, 1, 2); + } + + private void parseFingerprintLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + if (lineNoOpt.length() != "fingerprint".length() + 5 * 10) { + throw new DescriptorParseException("Illegal line '" + line + "'."); + } + this.fingerprint = ParseHelper.parseTwentyByteHexString(line, + lineNoOpt.substring("fingerprint ".length()).replaceAll(" ", "")); + } + + private void parseHibernatingLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + if (partsNoOpt.length != 2) { + throw new DescriptorParseException("Illegal line '" + line + "'."); + } + if (partsNoOpt[1].equals("1")) { + this.hibernating = true; + } else if (partsNoOpt[1].equals("0")) { + this.hibernating = false; + } else { + throw new DescriptorParseException("Illegal line '" + line + "'."); + } + } + + private void parseUptimeLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + if (partsNoOpt.length != 2) { + throw new DescriptorParseException("Wrong number of values in line " + + "'" + line + "'."); + } + boolean isValid = false; + try { + this.uptime = Integer.parseInt(partsNoOpt[1]); + if (this.uptime >= 0) { + isValid = true; + } + } catch (NumberFormatException e) { + /* Handle below. */ + } + if (!isValid) { + throw new DescriptorParseException("Illegal value in line '" + line + + "'."); + } + } + + private void parseOnionKeyLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* Not parsing crypto parts (yet). */ + } + + private void parseSigningKeyLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + /* Not parsing crypto parts (yet). */ + } + + private void parseAcceptLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + this.parseExitPolicyLine(line, lineNoOpt, partsNoOpt); + } + + private void parseRejectLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + this.parseExitPolicyLine(line, lineNoOpt, partsNoOpt); + } + + private void parseExitPolicyLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + if (partsNoOpt.length != 2) { + throw new DescriptorParseException("Illegal line '" + line + "'."); + } + ParseHelper.parseExitPattern(line, partsNoOpt[1]); + this.exitPolicyLines.add(lineNoOpt); + } + + private void parseRouterSignatureLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + if (!lineNoOpt.equals("router-signature")) { + throw new DescriptorParseException("Illegal line '" + line + "'."); + } + /* Not parsing crypto parts (yet). */ + } + + private void parseContactLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + if (lineNoOpt.length() > "contact ".length()) { + this.contact = lineNoOpt.substring("contact ".length()); + } else { + this.contact = ""; + } + } + + private void parseFamilyLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + this.familyEntries = new ArrayList<String>(); + for (int i = 1; i < partsNoOpt.length; i++) { + if (partsNoOpt[i].startsWith("$")) { + this.familyEntries.add("$" + + ParseHelper.parseTwentyByteHexString(line, + partsNoOpt[i].substring(1))); + } else { + this.familyEntries.add(ParseHelper.parseNickname(line, + partsNoOpt[i])); + } + } + } + + private void parseReadHistoryLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + this.readHistory = new BandwidthHistoryImpl(line, lineNoOpt, + partsNoOpt); + } + + private void parseWriteHistoryLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + this.writeHistory = new BandwidthHistoryImpl(line, lineNoOpt, + partsNoOpt); + } + + private void parseEventdnsLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + if (partsNoOpt.length != 2) { + throw new DescriptorParseException("Illegal line '" + line + "'."); + } + if (partsNoOpt[1].equals("true")) { + this.usesEnhancedDnsLogic = true; + } else if (partsNoOpt[1].equals("false")) { + this.usesEnhancedDnsLogic = false; + } else { + throw new DescriptorParseException("Illegal line '" + line + "'."); + } + } + + private void parseCachesExtraInfoLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + if (!lineNoOpt.equals("caches-extra-info")) { + throw new DescriptorParseException("Illegal line '" + line + "'."); + } + this.cachesExtraInfo = true; + } + + private void parseExtraInfoDigestLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + if (partsNoOpt.length != 2) { + throw new DescriptorParseException("Illegal line '" + line + "'."); + } + this.extraInfoDigest = ParseHelper.parseTwentyByteHexString(line, + partsNoOpt[1]); + } + + private void parseHiddenServiceDirLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + this.hiddenServiceDirVersions = new ArrayList<Integer>(); + if (partsNoOpt.length == 1) { + this.hiddenServiceDirVersions.add(2); + } else { + try { + for (int i = 1; i < partsNoOpt.length; i++) { + this.hiddenServiceDirVersions.add(Integer.parseInt( + partsNoOpt[i])); + } + } catch (NumberFormatException e) { + throw new DescriptorParseException("Illegal value in line '" + + line + "'."); + } + } + } + + private void parseProtocolsLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + List<String> partsList = Arrays.asList(partsNoOpt); + boolean isValid = true; + this.linkProtocolVersions = new ArrayList<Integer>(); + this.circuitProtocolVersions = new ArrayList<Integer>(); + List<Integer> protocolVersions = null; + for (int i = 1; i < partsNoOpt.length; i++) { + String part = partsNoOpt[i]; + if (part.equals("Link")) { + protocolVersions = this.linkProtocolVersions; + } else if (part.equals("Circuit")) { + protocolVersions = this.circuitProtocolVersions; + } else if (protocolVersions == null) { + isValid = false; + break; + } else { + try { + protocolVersions.add(Integer.parseInt(part)); + } catch (NumberFormatException e) { + isValid = false; + break; + } + } + } + if (protocolVersions != this.circuitProtocolVersions) { + isValid = false; + } + if (!isValid) { + throw new DescriptorParseException("Illegal line '" + line + "'."); + } + } + + private void parseAllowSingleHopExitsLine(String line, String lineNoOpt, + String[] partsNoOpt) throws DescriptorParseException { + if (!lineNoOpt.equals("allow-single-hop-exits")) { + throw new DescriptorParseException("Illegal line '" + line + "'."); + } + this.allowSingleHopExits = true; + } + + private String nickname; + public String getNickname() { + return this.nickname; + } + + private String address; + public String getAddress() { + return this.address; + } + + private int orPort; + public int getOrPort() { + return this.orPort; + } + + private int socksPort; + public int getSocksPort() { + return this.socksPort; + } + + private int dirPort; + public int getDirPort() { + return this.dirPort; + } + + private int bandwidthRate; + public int getBandwidthRate() { + return this.bandwidthRate; + } + + private int bandwidthBurst; + public int getBandwidthBurst() { + return this.bandwidthBurst; + } + + private int bandwidthObserved; + public int getBandwidthObserved() { + return this.bandwidthObserved; + } + + private String platform; + public String getPlatform() { + return this.platform; + } + + private long publishedMillis; + public long getPublishedMillis() { + return this.publishedMillis; + } + + private String fingerprint; + public String getFingerprint() { + return this.fingerprint; + } + + private boolean hibernating; + public boolean isHibernating() { + return this.hibernating; + } + + private int uptime = -1; + public int getUptime() { + return this.uptime; + } + + private List<String> exitPolicyLines = new ArrayList<String>(); + public List<String> getExitPolicyLines() { + return new ArrayList<String>(this.exitPolicyLines); + } + + private String contact; + public String getContact() { + return this.contact; + } + + private List<String> familyEntries; + public List<String> getFamilyEntries() { + return this.familyEntries == null ? null : + new ArrayList<String>(this.familyEntries); + } + + private BandwidthHistory readHistory; + public BandwidthHistory getReadHistory() { + return this.readHistory; + } + + private BandwidthHistory writeHistory; + public BandwidthHistory getWriteHistory() { + return this.writeHistory; + } + + private boolean usesEnhancedDnsLogic; + public boolean getUsesEnhancedDnsLogic() { + return this.usesEnhancedDnsLogic; + } + + private boolean cachesExtraInfo; + public boolean getCachesExtraInfo() { + return this.cachesExtraInfo; + } + + private String extraInfoDigest; + public String getExtraInfoDigest() { + return this.extraInfoDigest; + } + + private List<Integer> hiddenServiceDirVersions; + public List<Integer> getHiddenServiceDirVersions() { + return this.hiddenServiceDirVersions == null ? null : + new ArrayList<Integer>(this.hiddenServiceDirVersions); + } + + private List<Integer> linkProtocolVersions; + public List<Integer> getLinkProtocolVersions() { + return this.linkProtocolVersions == null ? null : + new ArrayList<Integer>(this.linkProtocolVersions); + } + + private List<Integer> circuitProtocolVersions; + public List<Integer> getCircuitProtocolVersions() { + return this.circuitProtocolVersions == null ? null : + new ArrayList<Integer>(this.circuitProtocolVersions); + } + + private boolean allowSingleHopExits; + public boolean getAllowSingleHopExits() { + return this.allowSingleHopExits; + } +} + diff --git a/test/org/torproject/descriptor/impl/RelayServerDescriptorImplTest.java b/test/org/torproject/descriptor/impl/RelayServerDescriptorImplTest.java deleted file mode 100644 index f806502..0000000 --- a/test/org/torproject/descriptor/impl/RelayServerDescriptorImplTest.java +++ /dev/null @@ -1,1080 +0,0 @@ -/* Copyright 2012 The Tor Project - * See LICENSE for licensing information */ -package org.torproject.descriptor.impl; - -import org.torproject.descriptor.BandwidthHistory; -import org.torproject.descriptor.RelayServerDescriptor; - -import java.util.*; - -import org.junit.*; -import org.junit.rules.*; -import static org.junit.Assert.*; - -/* Test parsing of relay server descriptors. */ -public class RelayServerDescriptorImplTest { - - /* Helper class to build a descriptor based on default data and - * modifications requested by test methods. */ - private static class DescriptorBuilder { - private String routerLine = "router saberrider2008 94.134.192.243 " - + "9001 0 0"; - private static RelayServerDescriptor createWithRouterLine( - String line) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.routerLine = line; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String bandwidthLine = "bandwidth 51200 51200 53470"; - private static RelayServerDescriptor createWithBandwidthLine( - String line) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.bandwidthLine = line; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String platformLine = "platform Tor 0.2.2.35 " - + "(git-b04388f9e7546a9f) on Linux i686"; - private static RelayServerDescriptor createWithPlatformLine( - String line) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.platformLine = line; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String publishedLine = "published 2012-01-01 04:03:19"; - private static RelayServerDescriptor createWithPublishedLine( - String line) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.publishedLine = line; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String fingerprintLine = "opt fingerprint D873 3048 FC8E " - + "C910 2466 AD8F 3098 622B F1BF 71FD"; - private static RelayServerDescriptor createWithFingerprintLine( - String line) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.fingerprintLine = line; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String hibernatingLine = null; - private static RelayServerDescriptor createWithHibernatingLine( - String line) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.hibernatingLine = line; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String uptimeLine = "uptime 48"; - private static RelayServerDescriptor createWithUptimeLine( - String line) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.uptimeLine = line; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String onionKeyLines = "onion-key\n" - + "-----BEGIN RSA PUBLIC KEY-----\n" - + "MIGJAoGBAKM+iiHhO6eHsvd6Xjws9z9EQB1V/Bpuy5ciGJ1U4V9SeiKooSo5Bp" - + "PL\no3XT+6PIgzl3R6uycjS3Ejk47vLEJdcVTm/VG6E0ppu3olIynCI4QryfCE" - + "uC3cTF\n9wE4WXY4nX7w0RTN18UVLxrt1A9PP0cobFNiPs9rzJCbKFfacOkpAg" - + "MBAAE=\n" - + "-----END RSA PUBLIC KEY-----"; - private static RelayServerDescriptor createWithOnionKeyLines( - String lines) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.onionKeyLines = lines; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String signingKeyLines = "signing-key\n" - + "-----BEGIN RSA PUBLIC KEY-----\n" - + "MIGJAoGBALMm3r3QDh482Ewe6Ub9wvRIfmEkoNX6q5cEAtQRNHSDcNx41gjELb" - + "cl\nEniVMParBYACKfOxkS+mTTnIRDKVNEJTsDOwryNrc4X9JnPc/nn6ymYPiN" - + "DhUROG\n8URDIhQoixcUeyyrVB8sxliSstKimulGnB7xpjYOlO8JKaHLNL4TAg" - + "MBAAE=\n" - + "-----END RSA PUBLIC KEY-----"; - private static RelayServerDescriptor createWithSigningKeyLines( - String lines) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.signingKeyLines = lines; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String exitPolicyLines = "reject *:*"; - private static RelayServerDescriptor createWithExitPolicyLines( - String lines) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.exitPolicyLines = lines; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String contactLine = "contact Random Person <nobody AT " - + "example dot com>"; - private static RelayServerDescriptor createWithContactLine( - String line) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.contactLine = line; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String familyLine = null; - private static RelayServerDescriptor createWithFamilyLine( - String line) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.familyLine = line; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String readHistoryLine = null; - private static RelayServerDescriptor createWithReadHistoryLine( - String line) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.readHistoryLine = line; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String writeHistoryLine = null; - private static RelayServerDescriptor createWithWriteHistoryLine( - String line) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.writeHistoryLine = line; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String eventdnsLine = null; - private static RelayServerDescriptor createWithEventdnsLine( - String line) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.eventdnsLine = line; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String cachesExtraInfoLine = null; - private static RelayServerDescriptor createWithCachesExtraInfoLine( - String line) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.cachesExtraInfoLine = line; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String extraInfoDigestLine = "opt extra-info-digest " - + "1469D1550738A25B1E7B47CDDBCD7B2899F51B74"; - private static RelayServerDescriptor createWithExtraInfoDigestLine( - String line) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.extraInfoDigestLine = line; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String hiddenServiceDirLine = "opt hidden-service-dir"; - private static RelayServerDescriptor createWithHiddenServiceDirLine( - String line) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.hiddenServiceDirLine = line; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String protocolsLine = "opt protocols Link 1 2 Circuit 1"; - private static RelayServerDescriptor createWithProtocolsLine( - String line) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.protocolsLine = line; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String allowSingleHopExitsLine = null; - private static RelayServerDescriptor - createWithAllowSingleHopExitsLine(String line) - throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.allowSingleHopExitsLine = line; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private String routerSignatureLines = "router-signature\n" - + "-----BEGIN SIGNATURE-----\n" - + "o4j+kH8UQfjBwepUnr99v0ebN8RpzHJ/lqYsTojXHy9kMr1RNI9IDeSzA7PSqT" - + "uV\n4PL8QsGtlfwthtIoZpB2srZeyN/mcpA9fa1JXUrt/UN9K/+32Cyaad7h0n" - + "HE6Xfb\njqpXDpnBpvk4zjmzjjKYnIsUWTnADmu0fo3xTRqXi7g=\n" - + "-----END SIGNATURE-----"; - private static RelayServerDescriptor createWithRouterSignatureLines( - String line) throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - db.routerSignatureLines = line; - return new RelayServerDescriptorImpl(db.buildDescriptor()); - } - private byte[] buildDescriptor() { - StringBuilder sb = new StringBuilder(); - if (this.routerLine != null) { - sb.append(this.routerLine + "\n"); - } - if (this.bandwidthLine != null) { - sb.append(this.bandwidthLine + "\n"); - } - if (this.platformLine != null) { - sb.append(this.platformLine + "\n"); - } - if (this.publishedLine != null) { - sb.append(this.publishedLine + "\n"); - } - if (this.fingerprintLine != null) { - sb.append(this.fingerprintLine + "\n"); - } - if (this.hibernatingLine != null) { - sb.append(this.hibernatingLine + "\n"); - } - if (this.uptimeLine != null) { - sb.append(this.uptimeLine + "\n"); - } - if (this.onionKeyLines != null) { - sb.append(this.onionKeyLines + "\n"); - } - if (this.signingKeyLines != null) { - sb.append(this.signingKeyLines + "\n"); - } - if (this.exitPolicyLines != null) { - sb.append(this.exitPolicyLines + "\n"); - } - if (this.contactLine != null) { - sb.append(this.contactLine + "\n"); - } - if (this.familyLine != null) { - sb.append(this.familyLine + "\n"); - } - if (this.readHistoryLine != null) { - sb.append(this.readHistoryLine + "\n"); - } - if (this.writeHistoryLine != null) { - sb.append(this.writeHistoryLine + "\n"); - } - if (this.eventdnsLine != null) { - sb.append(this.eventdnsLine + "\n"); - } - if (this.cachesExtraInfoLine != null) { - sb.append(this.cachesExtraInfoLine + "\n"); - } - if (this.extraInfoDigestLine != null) { - sb.append(this.extraInfoDigestLine + "\n"); - } - if (this.hiddenServiceDirLine != null) { - sb.append(this.hiddenServiceDirLine + "\n"); - } - if (this.protocolsLine != null) { - sb.append(this.protocolsLine + "\n"); - } - if (this.allowSingleHopExitsLine != null) { - sb.append(this.allowSingleHopExitsLine + "\n"); - } - if (this.routerSignatureLines != null) { - sb.append(this.routerSignatureLines + "\n"); - } - return sb.toString().getBytes(); - } - } - - @Test() - public void testSampleDescriptor() throws DescriptorParseException { - DescriptorBuilder db = new DescriptorBuilder(); - RelayServerDescriptor descriptor = - new RelayServerDescriptorImpl(db.buildDescriptor()); - assertEquals("saberrider2008", descriptor.getNickname()); - assertEquals("94.134.192.243", descriptor.getAddress()); - assertEquals(9001, (int) descriptor.getOrPort()); - assertEquals(0, (int) descriptor.getSocksPort()); - assertEquals(0, (int) descriptor.getDirPort()); - assertEquals("Tor 0.2.2.35 (git-b04388f9e7546a9f) on Linux i686", - descriptor.getPlatform()); - assertEquals(Arrays.asList(new Integer[] {1, 2}), - descriptor.getLinkProtocolVersions()); - assertEquals(Arrays.asList(new Integer[] {1}), - descriptor.getCircuitProtocolVersions()); - assertEquals(1325390599000L, descriptor.getPublishedMillis()); - assertEquals("D8733048FC8EC9102466AD8F3098622BF1BF71FD", - descriptor.getFingerprint()); - assertEquals(48, (int) descriptor.getUptime()); - assertEquals(51200, (int) descriptor.getBandwidthRate()); - assertEquals(51200, (int) descriptor.getBandwidthBurst()); - assertEquals(53470, (int) descriptor.getBandwidthObserved()); - assertEquals("1469D1550738A25B1E7B47CDDBCD7B2899F51B74", - descriptor.getExtraInfoDigest()); - assertEquals(Arrays.asList(new Integer[] {2}), - descriptor.getHiddenServiceDirVersions()); - assertEquals("Random Person <nobody AT example dot com>", - descriptor.getContact()); - assertEquals(Arrays.asList(new String[] {"reject *:*"}), - descriptor.getExitPolicyLines()); - assertFalse(descriptor.isHibernating()); - assertNull(descriptor.getFamilyEntries()); - assertNull(descriptor.getReadHistory()); - assertNull(descriptor.getWriteHistory()); - assertFalse(descriptor.getUsesEnhancedDnsLogic()); - assertFalse(descriptor.getCachesExtraInfo()); - assertFalse(descriptor.getAllowSingleHopExits()); - } - - @Test(expected = DescriptorParseException.class) - public void testRouterLineMissing() throws DescriptorParseException { - DescriptorBuilder.createWithRouterLine(null); - } - - @Test() - public void testRouterOpt() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithRouterLine("opt router saberrider2008 " - + "94.134.192.243 9001 0 0"); - assertEquals("saberrider2008", descriptor.getNickname()); - assertEquals("94.134.192.243", descriptor.getAddress()); - assertEquals(9001, (int) descriptor.getOrPort()); - assertEquals(0, (int) descriptor.getSocksPort()); - assertEquals(0, (int) descriptor.getDirPort()); - } - - @Test(expected = DescriptorParseException.class) - public void testRouterLinePrecedingHibernatingLine() - throws DescriptorParseException { - DescriptorBuilder.createWithRouterLine("hibernating 1\nrouter " - + "saberrider2008 94.134.192.243 9001 0 0"); - } - - @Test(expected = DescriptorParseException.class) - public void testNicknameMissing() throws DescriptorParseException { - DescriptorBuilder.createWithRouterLine("router 94.134.192.243 9001 " - + "0 0"); - } - - @Test(expected = DescriptorParseException.class) - public void testNicknameInvalidChar() throws DescriptorParseException { - DescriptorBuilder.createWithRouterLine("router $aberrider2008 " - + "94.134.192.243 9001 0 0"); - } - - @Test(expected = DescriptorParseException.class) - public void testNicknameTooLong() throws DescriptorParseException { - DescriptorBuilder.createWithRouterLine("router " - + "saberrider2008ReallyLongNickname 94.134.192.243 9001 0 0"); - } - - @Test(expected = DescriptorParseException.class) - public void testAddress24() throws DescriptorParseException { - DescriptorBuilder.createWithRouterLine("router saberrider2008 " - + "94.134.192/24 9001 0 0"); - } - - @Test(expected = DescriptorParseException.class) - public void testAddress294() throws DescriptorParseException { - DescriptorBuilder.createWithRouterLine("router saberrider2008 " - + "294.134.192.243 9001 0 0"); - } - - @Test(expected = DescriptorParseException.class) - public void testAddressMissing() throws DescriptorParseException { - DescriptorBuilder.createWithRouterLine("router saberrider2008 9001 " - + "0 0"); - } - - @Test(expected = DescriptorParseException.class) - public void testOrPort99001() throws DescriptorParseException { - DescriptorBuilder.createWithRouterLine("router saberrider2008 " - + "94.134.192.243 99001 0 0"); - } - - @Test(expected = DescriptorParseException.class) - public void testOrPortMissing() throws DescriptorParseException { - DescriptorBuilder.createWithRouterLine("router saberrider2008 " - + "94.134.192.243 0 0"); - } - - @Test(expected = DescriptorParseException.class) - public void testOrPortOne() throws DescriptorParseException { - DescriptorBuilder.createWithRouterLine("router saberrider2008 " - + "94.134.192.243 one 0 0"); - } - - @Test(expected = DescriptorParseException.class) - public void testOrPortNewline() throws DescriptorParseException { - DescriptorBuilder.createWithRouterLine("router saberrider2008 " - + "94.134.192.243 0\n 0 0"); - } - - @Test(expected = DescriptorParseException.class) - public void testDirPortMissing() throws DescriptorParseException { - DescriptorBuilder.createWithRouterLine("router saberrider2008 " - + "94.134.192.243 9001 0 "); - } - - @Test() - public void testPlatformMissing() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithPlatformLine(null); - assertNull(descriptor.getPlatform()); - } - - @Test() - public void testPlatformOpt() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithPlatformLine("opt platform Tor 0.2.2.35 " - + "(git-b04388f9e7546a9f) on Linux i686"); - assertEquals("Tor 0.2.2.35 (git-b04388f9e7546a9f) on Linux i686", - descriptor.getPlatform()); - } - - @Test() - public void testPlatformNoSpace() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithPlatformLine("platform"); - assertEquals("", descriptor.getPlatform()); - } - - @Test() - public void testPlatformSpace() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithPlatformLine("platform "); - assertEquals("", descriptor.getPlatform()); - } - - @Test() - public void testProtocolsNoOpt() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithProtocolsLine("protocols Link 1 2 Circuit 1"); - assertEquals(Arrays.asList(new Integer[] {1, 2}), - descriptor.getLinkProtocolVersions()); - assertEquals(Arrays.asList(new Integer[] {1}), - descriptor.getCircuitProtocolVersions()); - } - - @Test(expected = DescriptorParseException.class) - public void testProtocolsAB() throws DescriptorParseException { - DescriptorBuilder.createWithProtocolsLine("opt protocols Link A B " - + "Circuit 1"); - } - - @Test(expected = DescriptorParseException.class) - public void testProtocolsNoCircuitVersions() - throws DescriptorParseException { - DescriptorBuilder.createWithProtocolsLine("opt protocols Link 1 2"); - } - - @Test(expected = DescriptorParseException.class) - public void testPublishedMissing() throws DescriptorParseException { - DescriptorBuilder.createWithPublishedLine(null); - } - - @Test() - public void testPublishedOpt() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithPublishedLine("opt published 2012-01-01 04:03:19"); - assertEquals(1325390599000L, descriptor.getPublishedMillis()); - } - - @Test(expected = DescriptorParseException.class) - public void testPublished3012() throws DescriptorParseException { - DescriptorBuilder.createWithPublishedLine("published 3012-01-01 " - + "04:03:19"); - } - - @Test(expected = DescriptorParseException.class) - public void testPublished1912() throws DescriptorParseException { - DescriptorBuilder.createWithPublishedLine("published 1912-01-01 " - + "04:03:19"); - } - - @Test(expected = DescriptorParseException.class) - public void testPublishedFeb31() throws DescriptorParseException { - DescriptorBuilder.createWithPublishedLine("published 2012-02-31 " - + "04:03:19"); - } - - @Test() - public void testFingerprintNoOpt() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithFingerprintLine("fingerprint D873 3048 FC8E C910 2466 " - + "AD8F 3098 622B F1BF 71FD"); - assertEquals("D8733048FC8EC9102466AD8F3098622BF1BF71FD", - descriptor.getFingerprint()); - } - - @Test(expected = DescriptorParseException.class) - public void testFingerprintG() throws DescriptorParseException { - DescriptorBuilder.createWithFingerprintLine("opt fingerprint G873 " - + "3048 FC8E C910 2466 AD8F 3098 622B F1BF 71FD"); - } - - @Test(expected = DescriptorParseException.class) - public void testFingerprintTooShort() throws DescriptorParseException { - DescriptorBuilder.createWithFingerprintLine("opt fingerprint D873 " - + "3048 FC8E C910 2466 AD8F 3098 622B F1BF"); - } - - @Test(expected = DescriptorParseException.class) - public void testFingerprintTooLong() throws DescriptorParseException { - DescriptorBuilder.createWithFingerprintLine("opt fingerprint D873 " - + "3048 FC8E C910 2466 AD8F 3098 622B F1BF 71FD D873"); - } - - @Test(expected = DescriptorParseException.class) - public void testFingerprintNoSpaces() throws DescriptorParseException { - DescriptorBuilder.createWithFingerprintLine("opt fingerprint " - + "D8733048FC8EC9102466AD8F3098622BF1BF71FD"); - } - - @Test() - public void testUptimeMissing() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithUptimeLine(null); - assertEquals(-1, (int) descriptor.getUptime()); - } - - @Test() - public void testUptimeOpt() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithUptimeLine("opt uptime 48"); - } - - @Test(expected = DescriptorParseException.class) - public void testUptimeFourtyEight() throws DescriptorParseException { - DescriptorBuilder.createWithUptimeLine("uptime fourty-eight"); - } - - @Test(expected = DescriptorParseException.class) - public void testUptimeMinusOne() throws DescriptorParseException { - DescriptorBuilder.createWithUptimeLine("uptime -1"); - } - - @Test(expected = DescriptorParseException.class) - public void testUptimeSpace() throws DescriptorParseException { - DescriptorBuilder.createWithUptimeLine("uptime "); - } - - @Test(expected = DescriptorParseException.class) - public void testUptimeNoSpace() throws DescriptorParseException { - DescriptorBuilder.createWithUptimeLine("uptime"); - } - - @Test(expected = DescriptorParseException.class) - public void testUptimeFourEight() throws DescriptorParseException { - DescriptorBuilder.createWithUptimeLine("uptime 4 8"); - } - - @Test() - public void testBandwidthOpt() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithBandwidthLine("opt bandwidth 51200 51200 53470"); - assertEquals(51200, (int) descriptor.getBandwidthRate()); - assertEquals(51200, (int) descriptor.getBandwidthBurst()); - assertEquals(53470, (int) descriptor.getBandwidthObserved()); - } - - @Test(expected = DescriptorParseException.class) - public void testBandwidthMissing() throws DescriptorParseException { - DescriptorBuilder.createWithBandwidthLine(null); - } - - @Test(expected = DescriptorParseException.class) - public void testBandwidthTwoValues() throws DescriptorParseException { - DescriptorBuilder.createWithBandwidthLine("bandwidth 51200 51200"); - } - - @Test(expected = DescriptorParseException.class) - public void testBandwidthFourValues() throws DescriptorParseException { - DescriptorBuilder.createWithBandwidthLine("bandwidth 51200 51200 " - + "53470 53470"); - } - - @Test(expected = DescriptorParseException.class) - public void testBandwidthMinusOneTwoThree() - throws DescriptorParseException { - DescriptorBuilder.createWithBandwidthLine("bandwidth -1 -2 -3"); - } - - @Test() - public void testExtraInfoDigestNoOpt() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithExtraInfoDigestLine("extra-info-digest " - + "1469D1550738A25B1E7B47CDDBCD7B2899F51B74"); - assertEquals("1469D1550738A25B1E7B47CDDBCD7B2899F51B74", - descriptor.getExtraInfoDigest()); - } - - @Test(expected = DescriptorParseException.class) - public void testExtraInfoDigestNoSpace() - throws DescriptorParseException { - DescriptorBuilder.createWithExtraInfoDigestLine("opt " - + "extra-info-digest"); - } - - @Test(expected = DescriptorParseException.class) - public void testExtraInfoDigestTooShort() - throws DescriptorParseException { - DescriptorBuilder.createWithExtraInfoDigestLine("opt " - + "extra-info-digest 1469D1550738A25B1E7B47CDDBCD7B2899F5"); - } - - @Test(expected = DescriptorParseException.class) - public void testExtraInfoDigestTooLong() - throws DescriptorParseException { - DescriptorBuilder.createWithExtraInfoDigestLine("opt " - + "extra-info-digest " - + "1469D1550738A25B1E7B47CDDBCD7B2899F51B741469"); - } - - @Test() - public void testExtraInfoDigestMissing() - throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithExtraInfoDigestLine(null); - assertNull(descriptor.getExtraInfoDigest()); - } - - @Test(expected = DescriptorParseException.class) - public void testOnionKeyMissing() throws DescriptorParseException { - DescriptorBuilder.createWithOnionKeyLines(null); - } - - @Test() - public void testOnionKeyOpt() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithOnionKeyLines("opt onion-key\n" - + "-----BEGIN RSA PUBLIC KEY-----\n" - + "MIGJAoGBAKM+iiHhO6eHsvd6Xjws9z9EQB1V/Bpuy5ciGJ1U4V9SeiKooSo5Bp" - + "PL\no3XT+6PIgzl3R6uycjS3Ejk47vLEJdcVTm/VG6E0ppu3olIynCI4QryfCE" - + "uC3cTF\n9wE4WXY4nX7w0RTN18UVLxrt1A9PP0cobFNiPs9rzJCbKFfacOkpAg" - + "MBAAE=\n" - + "-----END RSA PUBLIC KEY-----"); - } - - @Test(expected = DescriptorParseException.class) - public void testSigningKeyMissing() throws DescriptorParseException { - DescriptorBuilder.createWithSigningKeyLines(null); - } - - @Test() - public void testSigningKeyOpt() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithSigningKeyLines("opt signing-key\n" - + "-----BEGIN RSA PUBLIC KEY-----\n" - + "MIGJAoGBALMm3r3QDh482Ewe6Ub9wvRIfmEkoNX6q5cEAtQRNHSDcNx41gjELb" - + "cl\nEniVMParBYACKfOxkS+mTTnIRDKVNEJTsDOwryNrc4X9JnPc/nn6ymYPiN" - + "DhUROG\n8URDIhQoixcUeyyrVB8sxliSstKimulGnB7xpjYOlO8JKaHLNL4TAg" - + "MBAAE=\n" - + "-----END RSA PUBLIC KEY-----"); - } - - @Test() - public void testHiddenServiceDirMissing() - throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithHiddenServiceDirLine(null); - assertNull(descriptor.getHiddenServiceDirVersions()); - } - - @Test() - public void testHiddenServiceDirNoOpt() - throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithHiddenServiceDirLine("hidden-service-dir"); - assertEquals(Arrays.asList(new Integer[] {2}), - descriptor.getHiddenServiceDirVersions()); - } - - @Test() - public void testHiddenServiceDirVersions2And3() - throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithHiddenServiceDirLine("hidden-service-dir 2 3"); - assertEquals(Arrays.asList(new Integer[] {2, 3}), - descriptor.getHiddenServiceDirVersions()); - } - - @Test() - public void testContactMissing() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithContactLine(null); - assertNull(descriptor.getContact()); - } - - @Test() - public void testContactOpt() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithContactLine("opt contact Random Person"); - assertEquals("Random Person", descriptor.getContact()); - } - - @Test(expected = DescriptorParseException.class) - public void testContactDuplicate() throws DescriptorParseException { - DescriptorBuilder.createWithContactLine("contact Random " - + "Person\ncontact Random Person"); - } - - @Test() - public void testContactNoSpace() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithContactLine("contact"); - assertEquals("", descriptor.getContact()); - } - - @Test() - public void testExitPolicyRejectAllAcceptAll() - throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithExitPolicyLines("reject *:*\naccept *:*"); - assertEquals(Arrays.asList(new String[] {"reject *:*", "accept *:*"}), - descriptor.getExitPolicyLines()); - } - - @Test() - public void testExitPolicyOpt() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithExitPolicyLines("opt reject *:*"); - assertEquals(Arrays.asList(new String[] {"reject *:*"}), - descriptor.getExitPolicyLines()); - } - - @Test(expected = DescriptorParseException.class) - public void testExitPolicyNoPort() throws DescriptorParseException { - DescriptorBuilder.createWithExitPolicyLines("reject *"); - } - - @Test() - public void testExitPolicyAccept80RejectAll() - throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithExitPolicyLines("accept *:80\nreject *:*"); - assertEquals(Arrays.asList(new String[] {"accept *:80", - "reject *:*"}), descriptor.getExitPolicyLines()); - } - - @Test(expected = DescriptorParseException.class) - public void testExitPolicyReject321() throws DescriptorParseException { - DescriptorBuilder.createWithExitPolicyLines("reject " - + "123.123.123.321:80"); - } - - @Test(expected = DescriptorParseException.class) - public void testExitPolicyRejectPort66666() - throws DescriptorParseException { - DescriptorBuilder.createWithExitPolicyLines("reject *:66666"); - } - - @Test(expected = DescriptorParseException.class) - public void testExitPolicyProjectAll() throws DescriptorParseException { - DescriptorBuilder.createWithExitPolicyLines("project *:*"); - } - - @Test(expected = DescriptorParseException.class) - public void testExitPolicyMissing() throws DescriptorParseException { - DescriptorBuilder.createWithExitPolicyLines(null); - } - - @Test(expected = DescriptorParseException.class) - public void testRouterSignatureMissing() - throws DescriptorParseException { - DescriptorBuilder.createWithRouterSignatureLines(null); - } - - @Test() - public void testRouterSignatureOpt() - throws DescriptorParseException { - DescriptorBuilder.createWithRouterSignatureLines("opt " - + "router-signature\n" - + "-----BEGIN SIGNATURE-----\n" - + "crypto lines are ignored anyway\n" - + "-----END SIGNATURE-----"); - } - - @Test(expected = DescriptorParseException.class) - public void testRouterSignatureNotLastLine() - throws DescriptorParseException { - DescriptorBuilder.createWithRouterSignatureLines("router-signature\n" - + "-----BEGIN SIGNATURE-----\n" - + "o4j+kH8UQfjBwepUnr99v0ebN8RpzHJ/lqYsTojXHy9kMr1RNI9IDeSzA7PSqT" - + "uV\n4PL8QsGtlfwthtIoZpB2srZeyN/mcpA9fa1JXUrt/UN9K/+32Cyaad7h0n" - + "HE6Xfb\njqpXDpnBpvk4zjmzjjKYnIsUWTnADmu0fo3xTRqXi7g=\n" - + "-----END SIGNATURE-----\ncontact me"); - } - - @Test() - public void testHibernatingOpt() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithHibernatingLine("opt hibernating 1"); - assertTrue(descriptor.isHibernating()); - } - - @Test() - public void testHibernatingFalse() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithHibernatingLine("hibernating 0"); - assertFalse(descriptor.isHibernating()); - } - - @Test() - public void testHibernatingTrue() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithHibernatingLine("hibernating 1"); - assertTrue(descriptor.isHibernating()); - } - - @Test(expected = DescriptorParseException.class) - public void testHibernatingYep() throws DescriptorParseException { - DescriptorBuilder.createWithHibernatingLine("hibernating yep"); - } - - @Test(expected = DescriptorParseException.class) - public void testHibernatingNoSpace() throws DescriptorParseException { - DescriptorBuilder.createWithHibernatingLine("hibernating"); - } - - @Test() - public void testFamilyOpt() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithFamilyLine("opt family saberrider2008"); - assertEquals(Arrays.asList(new String[] {"saberrider2008"}), - descriptor.getFamilyEntries()); - } - - @Test() - public void testFamilyFingerprint() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithFamilyLine("family " - + "$D8733048FC8EC9102466AD8F3098622BF1BF71FD"); - assertEquals(Arrays.asList(new String[] { - "$D8733048FC8EC9102466AD8F3098622BF1BF71FD"}), - descriptor.getFamilyEntries()); - } - - @Test() - public void testFamilyNickname() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithFamilyLine("family saberrider2008"); - assertEquals(Arrays.asList(new String[] {"saberrider2008"}), - descriptor.getFamilyEntries()); - } - - @Test(expected = DescriptorParseException.class) - public void testFamilyDuplicate() throws DescriptorParseException { - DescriptorBuilder.createWithFamilyLine("family " - + "saberrider2008\nfamily saberrider2008"); - } - - @Test(expected = DescriptorParseException.class) - public void testFamilyNicknamePrefix() throws DescriptorParseException { - DescriptorBuilder.createWithFamilyLine("family $saberrider2008"); - } - - @Test(expected = DescriptorParseException.class) - public void testFamilyFingerprintNoPrefix() - throws DescriptorParseException { - DescriptorBuilder.createWithFamilyLine("family " - + "D8733048FC8EC9102466AD8F3098622BF1BF71FD"); - } - - @Test() - public void testWriteHistory() throws DescriptorParseException { - String writeHistoryLine = "write-history 2012-01-01 03:51:44 (900 s) " - + "4345856,261120,7591936,1748992"; - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithWriteHistoryLine(writeHistoryLine); - assertNotNull(descriptor.getWriteHistory()); - BandwidthHistory parsedWriteHistory = descriptor.getWriteHistory(); - assertEquals(writeHistoryLine, parsedWriteHistory.getLine()); - assertEquals(1325389904000L, (long) parsedWriteHistory. - getHistoryEndMillis()); - assertEquals(900L, (long) parsedWriteHistory.getIntervalLength()); - SortedMap<Long, Long> bandwidthValues = parsedWriteHistory. - getBandwidthValues(); - assertEquals(4345856L, (long) bandwidthValues.remove(1325387204000L)); - assertEquals(261120L, (long) bandwidthValues.remove(1325388104000L)); - assertEquals(7591936L, (long) bandwidthValues.remove(1325389004000L)); - assertEquals(1748992L, (long) bandwidthValues.remove(1325389904000L)); - assertTrue(bandwidthValues.isEmpty()); - } - - @Test() - public void testWriteHistoryOpt() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithWriteHistoryLine("opt write-history 2012-01-01 " - + "03:51:44 (900 s) 4345856,261120,7591936,1748992"); - assertNotNull(descriptor.getWriteHistory()); - } - - @Test(expected = DescriptorParseException.class) - public void testWriteHistory3012() throws DescriptorParseException { - DescriptorBuilder.createWithWriteHistoryLine("write-history " - + "3012-01-01 03:51:44 (900 s) 4345856,261120,7591936,1748992"); - } - - @Test(expected = DescriptorParseException.class) - public void testWriteHistoryNoSeconds() - throws DescriptorParseException { - DescriptorBuilder.createWithWriteHistoryLine("write-history " - + "2012-01-01 03:51 (900 s) 4345856,261120,7591936,1748992"); - } - - @Test(expected = DescriptorParseException.class) - public void testWriteHistoryNoParathenses() - throws DescriptorParseException { - DescriptorBuilder.createWithWriteHistoryLine("write-history " - + "2012-01-01 03:51:44 900 s 4345856,261120,7591936,1748992"); - } - - @Test(expected = DescriptorParseException.class) - public void testWriteHistoryNoSpaceSeconds() - throws DescriptorParseException { - DescriptorBuilder.createWithWriteHistoryLine("write-history " - + "2012-01-01 03:51:44 (900s) 4345856,261120,7591936,1748992"); - } - - @Test(expected = DescriptorParseException.class) - public void testWriteHistoryTrailingComma() - throws DescriptorParseException { - DescriptorBuilder.createWithWriteHistoryLine("write-history " - + "2012-01-01 03:51:44 (900 s) 4345856,261120,7591936,"); - } - - @Test(expected = DescriptorParseException.class) - public void testWriteHistoryOneTwoThree() - throws DescriptorParseException { - DescriptorBuilder.createWithWriteHistoryLine("write-history " - + "2012-01-01 03:51:44 (900 s) one,two,three"); - } - - @Test() - public void testWriteHistoryNoValuesSpace() - throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithWriteHistoryLine("write-history 2012-01-01 03:51:44 " - + "(900 s) "); - assertEquals(900, (long) descriptor.getWriteHistory(). - getIntervalLength()); - assertTrue(descriptor.getWriteHistory().getBandwidthValues(). - isEmpty()); - } - - @Test() - public void testWriteHistoryNoValuesNoSpace() - throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithWriteHistoryLine("write-history 2012-01-01 03:51:44 " - + "(900 s)"); - assertEquals(900, (long) descriptor.getWriteHistory(). - getIntervalLength()); - assertTrue(descriptor.getWriteHistory().getBandwidthValues(). - isEmpty()); - } - - @Test(expected = DescriptorParseException.class) - public void testWriteHistoryNoS() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithWriteHistoryLine("write-history 2012-01-01 03:51:44 " - + "(900 "); - } - - @Test(expected = DescriptorParseException.class) - public void testWriteHistoryTrailingNumber() - throws DescriptorParseException { - DescriptorBuilder.createWithWriteHistoryLine("write-history " - + "2012-01-01 03:51:44 (900 s) 4345856 1"); - } - - @Test() - public void testWriteHistory1800Seconds() - throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithWriteHistoryLine("write-history 2012-01-01 03:51:44 " - + "(1800 s) 4345856"); - assertEquals(1800L, (long) descriptor.getWriteHistory(). - getIntervalLength()); - } - - @Test() - public void testReadHistory() throws DescriptorParseException { - String readHistoryLine = "read-history 2012-01-01 03:51:44 (900 s) " - + "4268032,139264,7797760,1415168"; - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithReadHistoryLine(readHistoryLine); - assertNotNull(descriptor.getReadHistory()); - BandwidthHistory parsedReadHistory = descriptor.getReadHistory(); - assertEquals(readHistoryLine, parsedReadHistory.getLine()); - assertEquals(1325389904000L, (long) parsedReadHistory. - getHistoryEndMillis()); - assertEquals(900L, (long) parsedReadHistory.getIntervalLength()); - SortedMap<Long, Long> bandwidthValues = parsedReadHistory. - getBandwidthValues(); - assertEquals(4268032L, (long) bandwidthValues.remove(1325387204000L)); - assertEquals(139264L, (long) bandwidthValues.remove(1325388104000L)); - assertEquals(7797760L, (long) bandwidthValues.remove(1325389004000L)); - assertEquals(1415168L, (long) bandwidthValues.remove(1325389904000L)); - assertTrue(bandwidthValues.isEmpty()); - } - - /* TODO There are some old server descriptors with " read-history" - * lines. Find out if these were spec-compliant and if other lines may - * start with leading spaces, too. */ - @Test(expected = DescriptorParseException.class) - public void testReadHistoryLeadingSpace() - throws DescriptorParseException { - String readHistoryLine = " read-history 2012-01-01 03:51:44 (900 s) " - + "4268032,139264,7797760,1415168"; - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithReadHistoryLine(readHistoryLine); - } - - @Test() - public void testEventdnsOpt() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithEventdnsLine("opt eventdns true"); - assertTrue(descriptor.getUsesEnhancedDnsLogic()); - } - - @Test() - public void testEventdnsTrue() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithEventdnsLine("eventdns true"); - assertTrue(descriptor.getUsesEnhancedDnsLogic()); - } - - @Test() - public void testEventdnsFalse() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithEventdnsLine("eventdns false"); - assertFalse(descriptor.getUsesEnhancedDnsLogic()); - } - - @Test(expected = DescriptorParseException.class) - public void testEventdns1() throws DescriptorParseException { - DescriptorBuilder.createWithEventdnsLine("eventdns 1"); - } - - @Test(expected = DescriptorParseException.class) - public void testEventdnsNo() throws DescriptorParseException { - DescriptorBuilder.createWithEventdnsLine("eventdns no"); - } - - @Test() - public void testCachesExtraInfoOpt() throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithCachesExtraInfoLine("opt caches-extra-info"); - assertTrue(descriptor.getCachesExtraInfo()); - } - - @Test() - public void testCachesExtraInfoNoSpace() - throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithCachesExtraInfoLine("caches-extra-info"); - assertTrue(descriptor.getCachesExtraInfo()); - } - - @Test(expected = DescriptorParseException.class) - public void testCachesExtraInfoTrue() throws DescriptorParseException { - DescriptorBuilder.createWithCachesExtraInfoLine("caches-extra-info " - + "true"); - } - - @Test() - public void testAllowSingleHopExitsOpt() - throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithCachesExtraInfoLine("opt allow-single-hop-exits"); - assertTrue(descriptor.getAllowSingleHopExits()); - } - - @Test() - public void testAllowSingleHopExitsNoSpace() - throws DescriptorParseException { - RelayServerDescriptor descriptor = DescriptorBuilder. - createWithCachesExtraInfoLine("allow-single-hop-exits"); - assertTrue(descriptor.getAllowSingleHopExits()); - } - - @Test(expected = DescriptorParseException.class) - public void testAllowSingleHopExitsTrue() - throws DescriptorParseException { - DescriptorBuilder.createWithCachesExtraInfoLine( - "allow-single-hop-exits true"); - } -} - diff --git a/test/org/torproject/descriptor/impl/ServerDescriptorImplTest.java b/test/org/torproject/descriptor/impl/ServerDescriptorImplTest.java new file mode 100644 index 0000000..c0721f5 --- /dev/null +++ b/test/org/torproject/descriptor/impl/ServerDescriptorImplTest.java @@ -0,0 +1,1080 @@ +/* Copyright 2012 The Tor Project + * See LICENSE for licensing information */ +package org.torproject.descriptor.impl; + +import org.torproject.descriptor.BandwidthHistory; +import org.torproject.descriptor.ServerDescriptor; + +import java.util.*; + +import org.junit.*; +import org.junit.rules.*; +import static org.junit.Assert.*; + +/* Test parsing of relay server descriptors. */ +public class ServerDescriptorImplTest { + + /* Helper class to build a descriptor based on default data and + * modifications requested by test methods. */ + private static class DescriptorBuilder { + private String routerLine = "router saberrider2008 94.134.192.243 " + + "9001 0 0"; + private static ServerDescriptor createWithRouterLine( + String line) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.routerLine = line; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String bandwidthLine = "bandwidth 51200 51200 53470"; + private static ServerDescriptor createWithBandwidthLine( + String line) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.bandwidthLine = line; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String platformLine = "platform Tor 0.2.2.35 " + + "(git-b04388f9e7546a9f) on Linux i686"; + private static ServerDescriptor createWithPlatformLine( + String line) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.platformLine = line; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String publishedLine = "published 2012-01-01 04:03:19"; + private static ServerDescriptor createWithPublishedLine( + String line) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.publishedLine = line; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String fingerprintLine = "opt fingerprint D873 3048 FC8E " + + "C910 2466 AD8F 3098 622B F1BF 71FD"; + private static ServerDescriptor createWithFingerprintLine( + String line) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.fingerprintLine = line; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String hibernatingLine = null; + private static ServerDescriptor createWithHibernatingLine( + String line) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.hibernatingLine = line; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String uptimeLine = "uptime 48"; + private static ServerDescriptor createWithUptimeLine( + String line) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.uptimeLine = line; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String onionKeyLines = "onion-key\n" + + "-----BEGIN RSA PUBLIC KEY-----\n" + + "MIGJAoGBAKM+iiHhO6eHsvd6Xjws9z9EQB1V/Bpuy5ciGJ1U4V9SeiKooSo5Bp" + + "PL\no3XT+6PIgzl3R6uycjS3Ejk47vLEJdcVTm/VG6E0ppu3olIynCI4QryfCE" + + "uC3cTF\n9wE4WXY4nX7w0RTN18UVLxrt1A9PP0cobFNiPs9rzJCbKFfacOkpAg" + + "MBAAE=\n" + + "-----END RSA PUBLIC KEY-----"; + private static ServerDescriptor createWithOnionKeyLines( + String lines) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.onionKeyLines = lines; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String signingKeyLines = "signing-key\n" + + "-----BEGIN RSA PUBLIC KEY-----\n" + + "MIGJAoGBALMm3r3QDh482Ewe6Ub9wvRIfmEkoNX6q5cEAtQRNHSDcNx41gjELb" + + "cl\nEniVMParBYACKfOxkS+mTTnIRDKVNEJTsDOwryNrc4X9JnPc/nn6ymYPiN" + + "DhUROG\n8URDIhQoixcUeyyrVB8sxliSstKimulGnB7xpjYOlO8JKaHLNL4TAg" + + "MBAAE=\n" + + "-----END RSA PUBLIC KEY-----"; + private static ServerDescriptor createWithSigningKeyLines( + String lines) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.signingKeyLines = lines; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String exitPolicyLines = "reject *:*"; + private static ServerDescriptor createWithExitPolicyLines( + String lines) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.exitPolicyLines = lines; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String contactLine = "contact Random Person <nobody AT " + + "example dot com>"; + private static ServerDescriptor createWithContactLine( + String line) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.contactLine = line; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String familyLine = null; + private static ServerDescriptor createWithFamilyLine( + String line) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.familyLine = line; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String readHistoryLine = null; + private static ServerDescriptor createWithReadHistoryLine( + String line) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.readHistoryLine = line; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String writeHistoryLine = null; + private static ServerDescriptor createWithWriteHistoryLine( + String line) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.writeHistoryLine = line; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String eventdnsLine = null; + private static ServerDescriptor createWithEventdnsLine( + String line) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.eventdnsLine = line; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String cachesExtraInfoLine = null; + private static ServerDescriptor createWithCachesExtraInfoLine( + String line) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.cachesExtraInfoLine = line; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String extraInfoDigestLine = "opt extra-info-digest " + + "1469D1550738A25B1E7B47CDDBCD7B2899F51B74"; + private static ServerDescriptor createWithExtraInfoDigestLine( + String line) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.extraInfoDigestLine = line; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String hiddenServiceDirLine = "opt hidden-service-dir"; + private static ServerDescriptor createWithHiddenServiceDirLine( + String line) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.hiddenServiceDirLine = line; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String protocolsLine = "opt protocols Link 1 2 Circuit 1"; + private static ServerDescriptor createWithProtocolsLine( + String line) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.protocolsLine = line; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String allowSingleHopExitsLine = null; + private static ServerDescriptor + createWithAllowSingleHopExitsLine(String line) + throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.allowSingleHopExitsLine = line; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private String routerSignatureLines = "router-signature\n" + + "-----BEGIN SIGNATURE-----\n" + + "o4j+kH8UQfjBwepUnr99v0ebN8RpzHJ/lqYsTojXHy9kMr1RNI9IDeSzA7PSqT" + + "uV\n4PL8QsGtlfwthtIoZpB2srZeyN/mcpA9fa1JXUrt/UN9K/+32Cyaad7h0n" + + "HE6Xfb\njqpXDpnBpvk4zjmzjjKYnIsUWTnADmu0fo3xTRqXi7g=\n" + + "-----END SIGNATURE-----"; + private static ServerDescriptor createWithRouterSignatureLines( + String line) throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + db.routerSignatureLines = line; + return new ServerDescriptorImpl(db.buildDescriptor()); + } + private byte[] buildDescriptor() { + StringBuilder sb = new StringBuilder(); + if (this.routerLine != null) { + sb.append(this.routerLine + "\n"); + } + if (this.bandwidthLine != null) { + sb.append(this.bandwidthLine + "\n"); + } + if (this.platformLine != null) { + sb.append(this.platformLine + "\n"); + } + if (this.publishedLine != null) { + sb.append(this.publishedLine + "\n"); + } + if (this.fingerprintLine != null) { + sb.append(this.fingerprintLine + "\n"); + } + if (this.hibernatingLine != null) { + sb.append(this.hibernatingLine + "\n"); + } + if (this.uptimeLine != null) { + sb.append(this.uptimeLine + "\n"); + } + if (this.onionKeyLines != null) { + sb.append(this.onionKeyLines + "\n"); + } + if (this.signingKeyLines != null) { + sb.append(this.signingKeyLines + "\n"); + } + if (this.exitPolicyLines != null) { + sb.append(this.exitPolicyLines + "\n"); + } + if (this.contactLine != null) { + sb.append(this.contactLine + "\n"); + } + if (this.familyLine != null) { + sb.append(this.familyLine + "\n"); + } + if (this.readHistoryLine != null) { + sb.append(this.readHistoryLine + "\n"); + } + if (this.writeHistoryLine != null) { + sb.append(this.writeHistoryLine + "\n"); + } + if (this.eventdnsLine != null) { + sb.append(this.eventdnsLine + "\n"); + } + if (this.cachesExtraInfoLine != null) { + sb.append(this.cachesExtraInfoLine + "\n"); + } + if (this.extraInfoDigestLine != null) { + sb.append(this.extraInfoDigestLine + "\n"); + } + if (this.hiddenServiceDirLine != null) { + sb.append(this.hiddenServiceDirLine + "\n"); + } + if (this.protocolsLine != null) { + sb.append(this.protocolsLine + "\n"); + } + if (this.allowSingleHopExitsLine != null) { + sb.append(this.allowSingleHopExitsLine + "\n"); + } + if (this.routerSignatureLines != null) { + sb.append(this.routerSignatureLines + "\n"); + } + return sb.toString().getBytes(); + } + } + + @Test() + public void testSampleDescriptor() throws DescriptorParseException { + DescriptorBuilder db = new DescriptorBuilder(); + ServerDescriptor descriptor = + new ServerDescriptorImpl(db.buildDescriptor()); + assertEquals("saberrider2008", descriptor.getNickname()); + assertEquals("94.134.192.243", descriptor.getAddress()); + assertEquals(9001, (int) descriptor.getOrPort()); + assertEquals(0, (int) descriptor.getSocksPort()); + assertEquals(0, (int) descriptor.getDirPort()); + assertEquals("Tor 0.2.2.35 (git-b04388f9e7546a9f) on Linux i686", + descriptor.getPlatform()); + assertEquals(Arrays.asList(new Integer[] {1, 2}), + descriptor.getLinkProtocolVersions()); + assertEquals(Arrays.asList(new Integer[] {1}), + descriptor.getCircuitProtocolVersions()); + assertEquals(1325390599000L, descriptor.getPublishedMillis()); + assertEquals("D8733048FC8EC9102466AD8F3098622BF1BF71FD", + descriptor.getFingerprint()); + assertEquals(48, (int) descriptor.getUptime()); + assertEquals(51200, (int) descriptor.getBandwidthRate()); + assertEquals(51200, (int) descriptor.getBandwidthBurst()); + assertEquals(53470, (int) descriptor.getBandwidthObserved()); + assertEquals("1469D1550738A25B1E7B47CDDBCD7B2899F51B74", + descriptor.getExtraInfoDigest()); + assertEquals(Arrays.asList(new Integer[] {2}), + descriptor.getHiddenServiceDirVersions()); + assertEquals("Random Person <nobody AT example dot com>", + descriptor.getContact()); + assertEquals(Arrays.asList(new String[] {"reject *:*"}), + descriptor.getExitPolicyLines()); + assertFalse(descriptor.isHibernating()); + assertNull(descriptor.getFamilyEntries()); + assertNull(descriptor.getReadHistory()); + assertNull(descriptor.getWriteHistory()); + assertFalse(descriptor.getUsesEnhancedDnsLogic()); + assertFalse(descriptor.getCachesExtraInfo()); + assertFalse(descriptor.getAllowSingleHopExits()); + } + + @Test(expected = DescriptorParseException.class) + public void testRouterLineMissing() throws DescriptorParseException { + DescriptorBuilder.createWithRouterLine(null); + } + + @Test() + public void testRouterOpt() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithRouterLine("opt router saberrider2008 " + + "94.134.192.243 9001 0 0"); + assertEquals("saberrider2008", descriptor.getNickname()); + assertEquals("94.134.192.243", descriptor.getAddress()); + assertEquals(9001, (int) descriptor.getOrPort()); + assertEquals(0, (int) descriptor.getSocksPort()); + assertEquals(0, (int) descriptor.getDirPort()); + } + + @Test(expected = DescriptorParseException.class) + public void testRouterLinePrecedingHibernatingLine() + throws DescriptorParseException { + DescriptorBuilder.createWithRouterLine("hibernating 1\nrouter " + + "saberrider2008 94.134.192.243 9001 0 0"); + } + + @Test(expected = DescriptorParseException.class) + public void testNicknameMissing() throws DescriptorParseException { + DescriptorBuilder.createWithRouterLine("router 94.134.192.243 9001 " + + "0 0"); + } + + @Test(expected = DescriptorParseException.class) + public void testNicknameInvalidChar() throws DescriptorParseException { + DescriptorBuilder.createWithRouterLine("router $aberrider2008 " + + "94.134.192.243 9001 0 0"); + } + + @Test(expected = DescriptorParseException.class) + public void testNicknameTooLong() throws DescriptorParseException { + DescriptorBuilder.createWithRouterLine("router " + + "saberrider2008ReallyLongNickname 94.134.192.243 9001 0 0"); + } + + @Test(expected = DescriptorParseException.class) + public void testAddress24() throws DescriptorParseException { + DescriptorBuilder.createWithRouterLine("router saberrider2008 " + + "94.134.192/24 9001 0 0"); + } + + @Test(expected = DescriptorParseException.class) + public void testAddress294() throws DescriptorParseException { + DescriptorBuilder.createWithRouterLine("router saberrider2008 " + + "294.134.192.243 9001 0 0"); + } + + @Test(expected = DescriptorParseException.class) + public void testAddressMissing() throws DescriptorParseException { + DescriptorBuilder.createWithRouterLine("router saberrider2008 9001 " + + "0 0"); + } + + @Test(expected = DescriptorParseException.class) + public void testOrPort99001() throws DescriptorParseException { + DescriptorBuilder.createWithRouterLine("router saberrider2008 " + + "94.134.192.243 99001 0 0"); + } + + @Test(expected = DescriptorParseException.class) + public void testOrPortMissing() throws DescriptorParseException { + DescriptorBuilder.createWithRouterLine("router saberrider2008 " + + "94.134.192.243 0 0"); + } + + @Test(expected = DescriptorParseException.class) + public void testOrPortOne() throws DescriptorParseException { + DescriptorBuilder.createWithRouterLine("router saberrider2008 " + + "94.134.192.243 one 0 0"); + } + + @Test(expected = DescriptorParseException.class) + public void testOrPortNewline() throws DescriptorParseException { + DescriptorBuilder.createWithRouterLine("router saberrider2008 " + + "94.134.192.243 0\n 0 0"); + } + + @Test(expected = DescriptorParseException.class) + public void testDirPortMissing() throws DescriptorParseException { + DescriptorBuilder.createWithRouterLine("router saberrider2008 " + + "94.134.192.243 9001 0 "); + } + + @Test() + public void testPlatformMissing() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithPlatformLine(null); + assertNull(descriptor.getPlatform()); + } + + @Test() + public void testPlatformOpt() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithPlatformLine("opt platform Tor 0.2.2.35 " + + "(git-b04388f9e7546a9f) on Linux i686"); + assertEquals("Tor 0.2.2.35 (git-b04388f9e7546a9f) on Linux i686", + descriptor.getPlatform()); + } + + @Test() + public void testPlatformNoSpace() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithPlatformLine("platform"); + assertEquals("", descriptor.getPlatform()); + } + + @Test() + public void testPlatformSpace() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithPlatformLine("platform "); + assertEquals("", descriptor.getPlatform()); + } + + @Test() + public void testProtocolsNoOpt() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithProtocolsLine("protocols Link 1 2 Circuit 1"); + assertEquals(Arrays.asList(new Integer[] {1, 2}), + descriptor.getLinkProtocolVersions()); + assertEquals(Arrays.asList(new Integer[] {1}), + descriptor.getCircuitProtocolVersions()); + } + + @Test(expected = DescriptorParseException.class) + public void testProtocolsAB() throws DescriptorParseException { + DescriptorBuilder.createWithProtocolsLine("opt protocols Link A B " + + "Circuit 1"); + } + + @Test(expected = DescriptorParseException.class) + public void testProtocolsNoCircuitVersions() + throws DescriptorParseException { + DescriptorBuilder.createWithProtocolsLine("opt protocols Link 1 2"); + } + + @Test(expected = DescriptorParseException.class) + public void testPublishedMissing() throws DescriptorParseException { + DescriptorBuilder.createWithPublishedLine(null); + } + + @Test() + public void testPublishedOpt() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithPublishedLine("opt published 2012-01-01 04:03:19"); + assertEquals(1325390599000L, descriptor.getPublishedMillis()); + } + + @Test(expected = DescriptorParseException.class) + public void testPublished3012() throws DescriptorParseException { + DescriptorBuilder.createWithPublishedLine("published 3012-01-01 " + + "04:03:19"); + } + + @Test(expected = DescriptorParseException.class) + public void testPublished1912() throws DescriptorParseException { + DescriptorBuilder.createWithPublishedLine("published 1912-01-01 " + + "04:03:19"); + } + + @Test(expected = DescriptorParseException.class) + public void testPublishedFeb31() throws DescriptorParseException { + DescriptorBuilder.createWithPublishedLine("published 2012-02-31 " + + "04:03:19"); + } + + @Test() + public void testFingerprintNoOpt() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithFingerprintLine("fingerprint D873 3048 FC8E C910 2466 " + + "AD8F 3098 622B F1BF 71FD"); + assertEquals("D8733048FC8EC9102466AD8F3098622BF1BF71FD", + descriptor.getFingerprint()); + } + + @Test(expected = DescriptorParseException.class) + public void testFingerprintG() throws DescriptorParseException { + DescriptorBuilder.createWithFingerprintLine("opt fingerprint G873 " + + "3048 FC8E C910 2466 AD8F 3098 622B F1BF 71FD"); + } + + @Test(expected = DescriptorParseException.class) + public void testFingerprintTooShort() throws DescriptorParseException { + DescriptorBuilder.createWithFingerprintLine("opt fingerprint D873 " + + "3048 FC8E C910 2466 AD8F 3098 622B F1BF"); + } + + @Test(expected = DescriptorParseException.class) + public void testFingerprintTooLong() throws DescriptorParseException { + DescriptorBuilder.createWithFingerprintLine("opt fingerprint D873 " + + "3048 FC8E C910 2466 AD8F 3098 622B F1BF 71FD D873"); + } + + @Test(expected = DescriptorParseException.class) + public void testFingerprintNoSpaces() throws DescriptorParseException { + DescriptorBuilder.createWithFingerprintLine("opt fingerprint " + + "D8733048FC8EC9102466AD8F3098622BF1BF71FD"); + } + + @Test() + public void testUptimeMissing() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithUptimeLine(null); + assertEquals(-1, (int) descriptor.getUptime()); + } + + @Test() + public void testUptimeOpt() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithUptimeLine("opt uptime 48"); + } + + @Test(expected = DescriptorParseException.class) + public void testUptimeFourtyEight() throws DescriptorParseException { + DescriptorBuilder.createWithUptimeLine("uptime fourty-eight"); + } + + @Test(expected = DescriptorParseException.class) + public void testUptimeMinusOne() throws DescriptorParseException { + DescriptorBuilder.createWithUptimeLine("uptime -1"); + } + + @Test(expected = DescriptorParseException.class) + public void testUptimeSpace() throws DescriptorParseException { + DescriptorBuilder.createWithUptimeLine("uptime "); + } + + @Test(expected = DescriptorParseException.class) + public void testUptimeNoSpace() throws DescriptorParseException { + DescriptorBuilder.createWithUptimeLine("uptime"); + } + + @Test(expected = DescriptorParseException.class) + public void testUptimeFourEight() throws DescriptorParseException { + DescriptorBuilder.createWithUptimeLine("uptime 4 8"); + } + + @Test() + public void testBandwidthOpt() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithBandwidthLine("opt bandwidth 51200 51200 53470"); + assertEquals(51200, (int) descriptor.getBandwidthRate()); + assertEquals(51200, (int) descriptor.getBandwidthBurst()); + assertEquals(53470, (int) descriptor.getBandwidthObserved()); + } + + @Test(expected = DescriptorParseException.class) + public void testBandwidthMissing() throws DescriptorParseException { + DescriptorBuilder.createWithBandwidthLine(null); + } + + @Test(expected = DescriptorParseException.class) + public void testBandwidthTwoValues() throws DescriptorParseException { + DescriptorBuilder.createWithBandwidthLine("bandwidth 51200 51200"); + } + + @Test(expected = DescriptorParseException.class) + public void testBandwidthFourValues() throws DescriptorParseException { + DescriptorBuilder.createWithBandwidthLine("bandwidth 51200 51200 " + + "53470 53470"); + } + + @Test(expected = DescriptorParseException.class) + public void testBandwidthMinusOneTwoThree() + throws DescriptorParseException { + DescriptorBuilder.createWithBandwidthLine("bandwidth -1 -2 -3"); + } + + @Test() + public void testExtraInfoDigestNoOpt() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithExtraInfoDigestLine("extra-info-digest " + + "1469D1550738A25B1E7B47CDDBCD7B2899F51B74"); + assertEquals("1469D1550738A25B1E7B47CDDBCD7B2899F51B74", + descriptor.getExtraInfoDigest()); + } + + @Test(expected = DescriptorParseException.class) + public void testExtraInfoDigestNoSpace() + throws DescriptorParseException { + DescriptorBuilder.createWithExtraInfoDigestLine("opt " + + "extra-info-digest"); + } + + @Test(expected = DescriptorParseException.class) + public void testExtraInfoDigestTooShort() + throws DescriptorParseException { + DescriptorBuilder.createWithExtraInfoDigestLine("opt " + + "extra-info-digest 1469D1550738A25B1E7B47CDDBCD7B2899F5"); + } + + @Test(expected = DescriptorParseException.class) + public void testExtraInfoDigestTooLong() + throws DescriptorParseException { + DescriptorBuilder.createWithExtraInfoDigestLine("opt " + + "extra-info-digest " + + "1469D1550738A25B1E7B47CDDBCD7B2899F51B741469"); + } + + @Test() + public void testExtraInfoDigestMissing() + throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithExtraInfoDigestLine(null); + assertNull(descriptor.getExtraInfoDigest()); + } + + @Test(expected = DescriptorParseException.class) + public void testOnionKeyMissing() throws DescriptorParseException { + DescriptorBuilder.createWithOnionKeyLines(null); + } + + @Test() + public void testOnionKeyOpt() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithOnionKeyLines("opt onion-key\n" + + "-----BEGIN RSA PUBLIC KEY-----\n" + + "MIGJAoGBAKM+iiHhO6eHsvd6Xjws9z9EQB1V/Bpuy5ciGJ1U4V9SeiKooSo5Bp" + + "PL\no3XT+6PIgzl3R6uycjS3Ejk47vLEJdcVTm/VG6E0ppu3olIynCI4QryfCE" + + "uC3cTF\n9wE4WXY4nX7w0RTN18UVLxrt1A9PP0cobFNiPs9rzJCbKFfacOkpAg" + + "MBAAE=\n" + + "-----END RSA PUBLIC KEY-----"); + } + + @Test(expected = DescriptorParseException.class) + public void testSigningKeyMissing() throws DescriptorParseException { + DescriptorBuilder.createWithSigningKeyLines(null); + } + + @Test() + public void testSigningKeyOpt() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithSigningKeyLines("opt signing-key\n" + + "-----BEGIN RSA PUBLIC KEY-----\n" + + "MIGJAoGBALMm3r3QDh482Ewe6Ub9wvRIfmEkoNX6q5cEAtQRNHSDcNx41gjELb" + + "cl\nEniVMParBYACKfOxkS+mTTnIRDKVNEJTsDOwryNrc4X9JnPc/nn6ymYPiN" + + "DhUROG\n8URDIhQoixcUeyyrVB8sxliSstKimulGnB7xpjYOlO8JKaHLNL4TAg" + + "MBAAE=\n" + + "-----END RSA PUBLIC KEY-----"); + } + + @Test() + public void testHiddenServiceDirMissing() + throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithHiddenServiceDirLine(null); + assertNull(descriptor.getHiddenServiceDirVersions()); + } + + @Test() + public void testHiddenServiceDirNoOpt() + throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithHiddenServiceDirLine("hidden-service-dir"); + assertEquals(Arrays.asList(new Integer[] {2}), + descriptor.getHiddenServiceDirVersions()); + } + + @Test() + public void testHiddenServiceDirVersions2And3() + throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithHiddenServiceDirLine("hidden-service-dir 2 3"); + assertEquals(Arrays.asList(new Integer[] {2, 3}), + descriptor.getHiddenServiceDirVersions()); + } + + @Test() + public void testContactMissing() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithContactLine(null); + assertNull(descriptor.getContact()); + } + + @Test() + public void testContactOpt() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithContactLine("opt contact Random Person"); + assertEquals("Random Person", descriptor.getContact()); + } + + @Test(expected = DescriptorParseException.class) + public void testContactDuplicate() throws DescriptorParseException { + DescriptorBuilder.createWithContactLine("contact Random " + + "Person\ncontact Random Person"); + } + + @Test() + public void testContactNoSpace() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithContactLine("contact"); + assertEquals("", descriptor.getContact()); + } + + @Test() + public void testExitPolicyRejectAllAcceptAll() + throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithExitPolicyLines("reject *:*\naccept *:*"); + assertEquals(Arrays.asList(new String[] {"reject *:*", "accept *:*"}), + descriptor.getExitPolicyLines()); + } + + @Test() + public void testExitPolicyOpt() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithExitPolicyLines("opt reject *:*"); + assertEquals(Arrays.asList(new String[] {"reject *:*"}), + descriptor.getExitPolicyLines()); + } + + @Test(expected = DescriptorParseException.class) + public void testExitPolicyNoPort() throws DescriptorParseException { + DescriptorBuilder.createWithExitPolicyLines("reject *"); + } + + @Test() + public void testExitPolicyAccept80RejectAll() + throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithExitPolicyLines("accept *:80\nreject *:*"); + assertEquals(Arrays.asList(new String[] {"accept *:80", + "reject *:*"}), descriptor.getExitPolicyLines()); + } + + @Test(expected = DescriptorParseException.class) + public void testExitPolicyReject321() throws DescriptorParseException { + DescriptorBuilder.createWithExitPolicyLines("reject " + + "123.123.123.321:80"); + } + + @Test(expected = DescriptorParseException.class) + public void testExitPolicyRejectPort66666() + throws DescriptorParseException { + DescriptorBuilder.createWithExitPolicyLines("reject *:66666"); + } + + @Test(expected = DescriptorParseException.class) + public void testExitPolicyProjectAll() throws DescriptorParseException { + DescriptorBuilder.createWithExitPolicyLines("project *:*"); + } + + @Test(expected = DescriptorParseException.class) + public void testExitPolicyMissing() throws DescriptorParseException { + DescriptorBuilder.createWithExitPolicyLines(null); + } + + @Test(expected = DescriptorParseException.class) + public void testRouterSignatureMissing() + throws DescriptorParseException { + DescriptorBuilder.createWithRouterSignatureLines(null); + } + + @Test() + public void testRouterSignatureOpt() + throws DescriptorParseException { + DescriptorBuilder.createWithRouterSignatureLines("opt " + + "router-signature\n" + + "-----BEGIN SIGNATURE-----\n" + + "crypto lines are ignored anyway\n" + + "-----END SIGNATURE-----"); + } + + @Test(expected = DescriptorParseException.class) + public void testRouterSignatureNotLastLine() + throws DescriptorParseException { + DescriptorBuilder.createWithRouterSignatureLines("router-signature\n" + + "-----BEGIN SIGNATURE-----\n" + + "o4j+kH8UQfjBwepUnr99v0ebN8RpzHJ/lqYsTojXHy9kMr1RNI9IDeSzA7PSqT" + + "uV\n4PL8QsGtlfwthtIoZpB2srZeyN/mcpA9fa1JXUrt/UN9K/+32Cyaad7h0n" + + "HE6Xfb\njqpXDpnBpvk4zjmzjjKYnIsUWTnADmu0fo3xTRqXi7g=\n" + + "-----END SIGNATURE-----\ncontact me"); + } + + @Test() + public void testHibernatingOpt() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithHibernatingLine("opt hibernating 1"); + assertTrue(descriptor.isHibernating()); + } + + @Test() + public void testHibernatingFalse() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithHibernatingLine("hibernating 0"); + assertFalse(descriptor.isHibernating()); + } + + @Test() + public void testHibernatingTrue() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithHibernatingLine("hibernating 1"); + assertTrue(descriptor.isHibernating()); + } + + @Test(expected = DescriptorParseException.class) + public void testHibernatingYep() throws DescriptorParseException { + DescriptorBuilder.createWithHibernatingLine("hibernating yep"); + } + + @Test(expected = DescriptorParseException.class) + public void testHibernatingNoSpace() throws DescriptorParseException { + DescriptorBuilder.createWithHibernatingLine("hibernating"); + } + + @Test() + public void testFamilyOpt() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithFamilyLine("opt family saberrider2008"); + assertEquals(Arrays.asList(new String[] {"saberrider2008"}), + descriptor.getFamilyEntries()); + } + + @Test() + public void testFamilyFingerprint() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithFamilyLine("family " + + "$D8733048FC8EC9102466AD8F3098622BF1BF71FD"); + assertEquals(Arrays.asList(new String[] { + "$D8733048FC8EC9102466AD8F3098622BF1BF71FD"}), + descriptor.getFamilyEntries()); + } + + @Test() + public void testFamilyNickname() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithFamilyLine("family saberrider2008"); + assertEquals(Arrays.asList(new String[] {"saberrider2008"}), + descriptor.getFamilyEntries()); + } + + @Test(expected = DescriptorParseException.class) + public void testFamilyDuplicate() throws DescriptorParseException { + DescriptorBuilder.createWithFamilyLine("family " + + "saberrider2008\nfamily saberrider2008"); + } + + @Test(expected = DescriptorParseException.class) + public void testFamilyNicknamePrefix() throws DescriptorParseException { + DescriptorBuilder.createWithFamilyLine("family $saberrider2008"); + } + + @Test(expected = DescriptorParseException.class) + public void testFamilyFingerprintNoPrefix() + throws DescriptorParseException { + DescriptorBuilder.createWithFamilyLine("family " + + "D8733048FC8EC9102466AD8F3098622BF1BF71FD"); + } + + @Test() + public void testWriteHistory() throws DescriptorParseException { + String writeHistoryLine = "write-history 2012-01-01 03:51:44 (900 s) " + + "4345856,261120,7591936,1748992"; + ServerDescriptor descriptor = DescriptorBuilder. + createWithWriteHistoryLine(writeHistoryLine); + assertNotNull(descriptor.getWriteHistory()); + BandwidthHistory parsedWriteHistory = descriptor.getWriteHistory(); + assertEquals(writeHistoryLine, parsedWriteHistory.getLine()); + assertEquals(1325389904000L, (long) parsedWriteHistory. + getHistoryEndMillis()); + assertEquals(900L, (long) parsedWriteHistory.getIntervalLength()); + SortedMap<Long, Long> bandwidthValues = parsedWriteHistory. + getBandwidthValues(); + assertEquals(4345856L, (long) bandwidthValues.remove(1325387204000L)); + assertEquals(261120L, (long) bandwidthValues.remove(1325388104000L)); + assertEquals(7591936L, (long) bandwidthValues.remove(1325389004000L)); + assertEquals(1748992L, (long) bandwidthValues.remove(1325389904000L)); + assertTrue(bandwidthValues.isEmpty()); + } + + @Test() + public void testWriteHistoryOpt() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithWriteHistoryLine("opt write-history 2012-01-01 " + + "03:51:44 (900 s) 4345856,261120,7591936,1748992"); + assertNotNull(descriptor.getWriteHistory()); + } + + @Test(expected = DescriptorParseException.class) + public void testWriteHistory3012() throws DescriptorParseException { + DescriptorBuilder.createWithWriteHistoryLine("write-history " + + "3012-01-01 03:51:44 (900 s) 4345856,261120,7591936,1748992"); + } + + @Test(expected = DescriptorParseException.class) + public void testWriteHistoryNoSeconds() + throws DescriptorParseException { + DescriptorBuilder.createWithWriteHistoryLine("write-history " + + "2012-01-01 03:51 (900 s) 4345856,261120,7591936,1748992"); + } + + @Test(expected = DescriptorParseException.class) + public void testWriteHistoryNoParathenses() + throws DescriptorParseException { + DescriptorBuilder.createWithWriteHistoryLine("write-history " + + "2012-01-01 03:51:44 900 s 4345856,261120,7591936,1748992"); + } + + @Test(expected = DescriptorParseException.class) + public void testWriteHistoryNoSpaceSeconds() + throws DescriptorParseException { + DescriptorBuilder.createWithWriteHistoryLine("write-history " + + "2012-01-01 03:51:44 (900s) 4345856,261120,7591936,1748992"); + } + + @Test(expected = DescriptorParseException.class) + public void testWriteHistoryTrailingComma() + throws DescriptorParseException { + DescriptorBuilder.createWithWriteHistoryLine("write-history " + + "2012-01-01 03:51:44 (900 s) 4345856,261120,7591936,"); + } + + @Test(expected = DescriptorParseException.class) + public void testWriteHistoryOneTwoThree() + throws DescriptorParseException { + DescriptorBuilder.createWithWriteHistoryLine("write-history " + + "2012-01-01 03:51:44 (900 s) one,two,three"); + } + + @Test() + public void testWriteHistoryNoValuesSpace() + throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithWriteHistoryLine("write-history 2012-01-01 03:51:44 " + + "(900 s) "); + assertEquals(900, (long) descriptor.getWriteHistory(). + getIntervalLength()); + assertTrue(descriptor.getWriteHistory().getBandwidthValues(). + isEmpty()); + } + + @Test() + public void testWriteHistoryNoValuesNoSpace() + throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithWriteHistoryLine("write-history 2012-01-01 03:51:44 " + + "(900 s)"); + assertEquals(900, (long) descriptor.getWriteHistory(). + getIntervalLength()); + assertTrue(descriptor.getWriteHistory().getBandwidthValues(). + isEmpty()); + } + + @Test(expected = DescriptorParseException.class) + public void testWriteHistoryNoS() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithWriteHistoryLine("write-history 2012-01-01 03:51:44 " + + "(900 "); + } + + @Test(expected = DescriptorParseException.class) + public void testWriteHistoryTrailingNumber() + throws DescriptorParseException { + DescriptorBuilder.createWithWriteHistoryLine("write-history " + + "2012-01-01 03:51:44 (900 s) 4345856 1"); + } + + @Test() + public void testWriteHistory1800Seconds() + throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithWriteHistoryLine("write-history 2012-01-01 03:51:44 " + + "(1800 s) 4345856"); + assertEquals(1800L, (long) descriptor.getWriteHistory(). + getIntervalLength()); + } + + @Test() + public void testReadHistory() throws DescriptorParseException { + String readHistoryLine = "read-history 2012-01-01 03:51:44 (900 s) " + + "4268032,139264,7797760,1415168"; + ServerDescriptor descriptor = DescriptorBuilder. + createWithReadHistoryLine(readHistoryLine); + assertNotNull(descriptor.getReadHistory()); + BandwidthHistory parsedReadHistory = descriptor.getReadHistory(); + assertEquals(readHistoryLine, parsedReadHistory.getLine()); + assertEquals(1325389904000L, (long) parsedReadHistory. + getHistoryEndMillis()); + assertEquals(900L, (long) parsedReadHistory.getIntervalLength()); + SortedMap<Long, Long> bandwidthValues = parsedReadHistory. + getBandwidthValues(); + assertEquals(4268032L, (long) bandwidthValues.remove(1325387204000L)); + assertEquals(139264L, (long) bandwidthValues.remove(1325388104000L)); + assertEquals(7797760L, (long) bandwidthValues.remove(1325389004000L)); + assertEquals(1415168L, (long) bandwidthValues.remove(1325389904000L)); + assertTrue(bandwidthValues.isEmpty()); + } + + /* TODO There are some old server descriptors with " read-history" + * lines. Find out if these were spec-compliant and if other lines may + * start with leading spaces, too. */ + @Test(expected = DescriptorParseException.class) + public void testReadHistoryLeadingSpace() + throws DescriptorParseException { + String readHistoryLine = " read-history 2012-01-01 03:51:44 (900 s) " + + "4268032,139264,7797760,1415168"; + ServerDescriptor descriptor = DescriptorBuilder. + createWithReadHistoryLine(readHistoryLine); + } + + @Test() + public void testEventdnsOpt() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithEventdnsLine("opt eventdns true"); + assertTrue(descriptor.getUsesEnhancedDnsLogic()); + } + + @Test() + public void testEventdnsTrue() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithEventdnsLine("eventdns true"); + assertTrue(descriptor.getUsesEnhancedDnsLogic()); + } + + @Test() + public void testEventdnsFalse() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithEventdnsLine("eventdns false"); + assertFalse(descriptor.getUsesEnhancedDnsLogic()); + } + + @Test(expected = DescriptorParseException.class) + public void testEventdns1() throws DescriptorParseException { + DescriptorBuilder.createWithEventdnsLine("eventdns 1"); + } + + @Test(expected = DescriptorParseException.class) + public void testEventdnsNo() throws DescriptorParseException { + DescriptorBuilder.createWithEventdnsLine("eventdns no"); + } + + @Test() + public void testCachesExtraInfoOpt() throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithCachesExtraInfoLine("opt caches-extra-info"); + assertTrue(descriptor.getCachesExtraInfo()); + } + + @Test() + public void testCachesExtraInfoNoSpace() + throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithCachesExtraInfoLine("caches-extra-info"); + assertTrue(descriptor.getCachesExtraInfo()); + } + + @Test(expected = DescriptorParseException.class) + public void testCachesExtraInfoTrue() throws DescriptorParseException { + DescriptorBuilder.createWithCachesExtraInfoLine("caches-extra-info " + + "true"); + } + + @Test() + public void testAllowSingleHopExitsOpt() + throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithCachesExtraInfoLine("opt allow-single-hop-exits"); + assertTrue(descriptor.getAllowSingleHopExits()); + } + + @Test() + public void testAllowSingleHopExitsNoSpace() + throws DescriptorParseException { + ServerDescriptor descriptor = DescriptorBuilder. + createWithCachesExtraInfoLine("allow-single-hop-exits"); + assertTrue(descriptor.getAllowSingleHopExits()); + } + + @Test(expected = DescriptorParseException.class) + public void testAllowSingleHopExitsTrue() + throws DescriptorParseException { + DescriptorBuilder.createWithCachesExtraInfoLine( + "allow-single-hop-exits true"); + } +} +
tor-commits@lists.torproject.org