commit b2ad143c2a79e335f0ff7648b1dcd5fc157af63c Author: Karsten Loesing karsten.loesing@gmx.net Date: Thu Feb 2 08:08:07 2012 +0100
Use a single interface for reading descriptors. --- .../descriptor/BridgeDescriptorReader.java | 34 --- .../descriptor/BridgePoolAssignmentReader.java | 34 --- .../descriptor/DescriptorDownloader.java | 109 ++++++++ .../torproject/descriptor/DescriptorReader.java | 34 +++ .../descriptor/DescriptorSourceFactory.java | 28 +-- .../descriptor/RelayDescriptorDownloader.java | 109 -------- .../descriptor/RelayDescriptorReader.java | 35 --- .../descriptor/impl/DescriptorDownloaderImpl.java | 265 ++++++++++++++++++++ .../descriptor/impl/DescriptorReaderImpl.java | 194 ++++++++++++++ .../impl/RelayDescriptorDownloaderImpl.java | 265 -------------------- .../impl/RelayOrBridgeDescriptorReaderImpl.java | 198 --------------- 11 files changed, 610 insertions(+), 695 deletions(-)
diff --git a/src/org/torproject/descriptor/BridgeDescriptorReader.java b/src/org/torproject/descriptor/BridgeDescriptorReader.java deleted file mode 100644 index d827124..0000000 --- a/src/org/torproject/descriptor/BridgeDescriptorReader.java +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright 2011, 2012 The Tor Project - * See LICENSE for licensing information */ -package org.torproject.descriptor; - -import java.io.File; -import java.util.Iterator; - -/* Read bridge descriptors from one or more local directories. */ -public interface BridgeDescriptorReader { - - /* Add a local directory to read bridge descriptors from. */ - public void addDirectory(File directory); - - /* Exclude files that are contained in the given history file and that - * haven't changed since they were last read. Add reads from the - * current run to the history file. Remove files that don't exist - * anymore from the history file. Lines in the history file contain the - * last modified timestamp and the absolute path of a file. */ - public void setExcludeFiles(File historyFile); - - /* Fail descriptor parsing when encountering an unrecognized line. This - * is not set by default, because the Tor specifications allow for new - * lines to be added that shall be ignored by older Tor versions. But - * some applications may want to handle unrecognized descriptor lines - * explicitly. */ - public void setFailUnrecognizedDescriptorLines(); - - /* Read the previously configured bridge descriptors and make them - * available via the returned blocking iterator. Whenever the reader - * runs out of descriptors and expects to provide more shortly after, it - * blocks the caller. This method can only be run once. */ - public Iterator<DescriptorFile> readDescriptors(); -} - diff --git a/src/org/torproject/descriptor/BridgePoolAssignmentReader.java b/src/org/torproject/descriptor/BridgePoolAssignmentReader.java deleted file mode 100644 index 13c8ae3..0000000 --- a/src/org/torproject/descriptor/BridgePoolAssignmentReader.java +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright 2011, 2012 The Tor Project - * See LICENSE for licensing information */ -package org.torproject.descriptor; - -import java.io.File; -import java.util.Iterator; - -/* Read bridge pool assignments from one or more local directories. */ -public interface BridgePoolAssignmentReader { - - /* Add a local directory to read bridge pool assignments from. */ - public void addDirectory(File directory); - - /* Exclude files that are contained in the given history file and that - * haven't changed since they were last read. Add reads from the - * current run to the history file. Remove files that don't exist - * anymore from the history file. Lines in the history file contain the - * last modified timestamp and the absolute path of a file. */ - public void setExcludeFiles(File historyFile); - - /* Fail descriptor parsing when encountering an unrecognized line. This - * is not set by default, because the Tor specifications allow for new - * lines to be added that shall be ignored by older Tor versions. But - * some applications may want to handle unrecognized descriptor lines - * explicitly. */ - public void setFailUnrecognizedDescriptorLines(); - - /* Read the previously configured bridge pool assignments and make them - * available via the returned blocking iterator. Whenever the reader - * runs out of descriptors and expects to provide more shortly after, it - * blocks the caller. This method can only be run once. */ - public Iterator<DescriptorFile> readDescriptors(); -} - diff --git a/src/org/torproject/descriptor/DescriptorDownloader.java b/src/org/torproject/descriptor/DescriptorDownloader.java new file mode 100644 index 0000000..5665e1f --- /dev/null +++ b/src/org/torproject/descriptor/DescriptorDownloader.java @@ -0,0 +1,109 @@ +/* Copyright 2011, 2012 The Tor Project + * See LICENSE for licensing information */ +package org.torproject.descriptor; + +import java.util.Iterator; +import java.util.Set; + +/* Download relay descriptors from directory mirrors or authorities. */ +public interface DescriptorDownloader { + + /* Add a directory authority to download descriptors from. A directory + * authority is only required for downloading network status vote and + * will be used when no directory mirrors are available. */ + public void addDirectoryAuthority(String nickname, String ip, + int dirPort); + + /* Add a directory mirror to download descriptors from. Directory + * mirrors are preferred when downloading descriptors, except for + * network status votes which are only available on directory + * authorities. */ + public void addDirectoryMirror(String nickname, String ip, int dirPort); + + /* Include the current network status consensus in the downloads. */ + public void setIncludeCurrentConsensus(); + + /* Include the current network status consensus in the downloads, and + * attempt to download it from all directory authorities. The primary + * purpose of doing this is to compare different consensuses and + * download characteristics to each other. Typically, downloading from + * a single directory mirror or authority is sufficient. */ + public void setIncludeCurrentConsensusFromAllDirectoryAuthorities(); + + /* Include the current network status votes referenced from a previously + * downloaded consensus in the downloads. This requires downloading the + * current consensus from at least one directory mirror or authority. */ + public void setIncludeCurrentReferencedVotes(); + + /* Include the current network status vote published by the given + * directory authority in the downloads. This requires downloading from + * at least one directory authority. */ + public void setIncludeCurrentVote(String fingerprint); + + /* Include the current network status votes published by the given + * directory authorities in the downloads. This requires downloading + * from at least one directory authority. */ + public void setIncludeCurrentVotes(Set<String> fingerprints); + + /* Include all server descriptors referenced from a previously + * downloaded network status consensus in the downloads. */ + public void setIncludeReferencedServerDescriptors(); + + /* Exclude the server descriptor with the given identifier from the + * downloads even if it's referenced from a consensus and we're supposed + * to download all referenced server descriptors. */ + public void setExcludeServerDescriptor(String identifier); + + /* Exclude the server descriptors with the given identifiers from the + * downloads even if they are referenced from a consensus and we're + * supposed to download all referenced server descriptors. */ + public void setExcludeServerDescriptors(Set<String> identifier); + + /* Include all extra-info descriptors referenced from previously + * downloaded server descriptors in the downloads. */ + public void setIncludeReferencedExtraInfoDescriptors(); + + /* Exclude the extra-info descriptor with the given identifier from the + * downloads even if it's referenced from a server descriptor and we're + * supposed to download all referenced extra-info descriptors. */ + public void setExcludeExtraInfoDescriptor(String identifier); + + /* Exclude the extra-info descriptors with the given identifiers from + * the downloads even if they are referenced from server descriptors + * and we're supposed to download all referenced extra-info + * descriptors. */ + public void setExcludeExtraInfoDescriptors(Set<String> identifiers); + + /* Define a connect timeout for a single request. If a timeout expires, + * no further requests will be sent to the directory authority or + * mirror. Setting this value to 0 disables the connect timeout. + * Default value is 1 minute (60 * 1000). */ + public void setConnectTimeout(long connectTimeoutMillis); + + /* Define a read timeout for a single request. If a timeout expires, + * no further requests will be sent to the directory authority or + * mirror. Setting this value to 0 disables the read timeout. + * Default value is 1 minute (60 * 1000). */ + public void setReadTimeout(long readTimeoutMillis); + + /* Define a global timeout for all requests. Once this timeout expires, + * all running requests are aborted and no further requests are made. + * Setting this value to 0 disables the global timeout. Default is 1 + * hour (60 * 60 * 1000). */ + public void setGlobalTimeout(long globalTimeoutMillis); + + /* Fail descriptor parsing when encountering an unrecognized line. This + * is not set by default, because the Tor specifications allow for new + * lines to be added that shall be ignored by older Tor versions. But + * some applications may want to handle unrecognized descriptor lines + * explicitly. */ + public void setFailUnrecognizedDescriptorLines(); + + /* Download the previously configured relay descriptors and make them + * available via the returned blocking iterator. Whenever the + * downloader runs out of descriptors and expects to provide more + * shortly after, it blocks the caller. This method can only be run + * once. */ + public Iterator<DescriptorRequest> downloadDescriptors(); +} + diff --git a/src/org/torproject/descriptor/DescriptorReader.java b/src/org/torproject/descriptor/DescriptorReader.java new file mode 100644 index 0000000..1d46a79 --- /dev/null +++ b/src/org/torproject/descriptor/DescriptorReader.java @@ -0,0 +1,34 @@ +/* Copyright 2011, 2012 The Tor Project + * See LICENSE for licensing information */ +package org.torproject.descriptor; + +import java.io.File; +import java.util.Iterator; + +/* Read descriptors from one or more local directories. */ +public interface DescriptorReader { + + /* Add a local directory to read descriptors from. */ + public void addDirectory(File directory); + + /* Exclude files that are contained in the given history file and that + * haven't changed since they were last read. Add reads from the + * current run to the history file. Remove files that don't exist + * anymore from the history file. Lines in the history file contain the + * last modified timestamp and the absolute path of a file. */ + public void setExcludeFiles(File historyFile); + + /* Fail descriptor parsing when encountering an unrecognized line. This + * is not set by default, because the Tor specifications allow for new + * lines to be added that shall be ignored by older Tor versions. But + * some applications may want to handle unrecognized descriptor lines + * explicitly. */ + public void setFailUnrecognizedDescriptorLines(); + + /* Read the previously configured descriptors and make them available + * via the returned blocking iterator. Whenever the reader runs out of + * descriptors and expects to provide more shortly after, it blocks the + * caller. This method can only be run once. */ + public Iterator<DescriptorFile> readDescriptors(); +} + diff --git a/src/org/torproject/descriptor/DescriptorSourceFactory.java b/src/org/torproject/descriptor/DescriptorSourceFactory.java index ed2790a..102bfce 100644 --- a/src/org/torproject/descriptor/DescriptorSourceFactory.java +++ b/src/org/torproject/descriptor/DescriptorSourceFactory.java @@ -2,32 +2,20 @@ * See LICENSE for licensing information */ package org.torproject.descriptor;
-import org.torproject.descriptor.impl.RelayDescriptorDownloaderImpl; -import org.torproject.descriptor.impl.RelayOrBridgeDescriptorReaderImpl; +import org.torproject.descriptor.impl.DescriptorDownloaderImpl; +import org.torproject.descriptor.impl.DescriptorReaderImpl;
/* Create descriptor source instances. */ public class DescriptorSourceFactory {
- /* Create a relay descriptor reader. */ - public static RelayDescriptorReader createRelayDescriptorReader() { - return new RelayOrBridgeDescriptorReaderImpl(); + /* Create a descriptor reader. */ + public static DescriptorReader createDescriptorReader() { + return new DescriptorReaderImpl(); }
- /* Create a relay descriptor downloader. */ - public static RelayDescriptorDownloader - createRelayDescriptorDownloader() { - return new RelayDescriptorDownloaderImpl(); - } - - /* Create a bridge descriptor reader. */ - public static BridgeDescriptorReader createBridgeDescriptorReader() { - return new RelayOrBridgeDescriptorReaderImpl(); - } - - /* Create a bridge pool assignment reader. */ - public static BridgePoolAssignmentReader - createBridgePoolAssignmentReader() { - return new RelayOrBridgeDescriptorReaderImpl(); + /* Create a descriptor downloader. */ + public static DescriptorDownloader createDescriptorDownloader() { + return new DescriptorDownloaderImpl(); } }
diff --git a/src/org/torproject/descriptor/RelayDescriptorDownloader.java b/src/org/torproject/descriptor/RelayDescriptorDownloader.java deleted file mode 100644 index 29171d3..0000000 --- a/src/org/torproject/descriptor/RelayDescriptorDownloader.java +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright 2011, 2012 The Tor Project - * See LICENSE for licensing information */ -package org.torproject.descriptor; - -import java.util.Iterator; -import java.util.Set; - -/* Download relay descriptors from directory mirrors or authorities. */ -public interface RelayDescriptorDownloader { - - /* Add a directory authority to download descriptors from. A directory - * authority is only required for downloading network status vote and - * will be used when no directory mirrors are available. */ - public void addDirectoryAuthority(String nickname, String ip, - int dirPort); - - /* Add a directory mirror to download descriptors from. Directory - * mirrors are preferred when downloading descriptors, except for - * network status votes which are only available on directory - * authorities. */ - public void addDirectoryMirror(String nickname, String ip, int dirPort); - - /* Include the current network status consensus in the downloads. */ - public void setIncludeCurrentConsensus(); - - /* Include the current network status consensus in the downloads, and - * attempt to download it from all directory authorities. The primary - * purpose of doing this is to compare different consensuses and - * download characteristics to each other. Typically, downloading from - * a single directory mirror or authority is sufficient. */ - public void setIncludeCurrentConsensusFromAllDirectoryAuthorities(); - - /* Include the current network status votes referenced from a previously - * downloaded consensus in the downloads. This requires downloading the - * current consensus from at least one directory mirror or authority. */ - public void setIncludeCurrentReferencedVotes(); - - /* Include the current network status vote published by the given - * directory authority in the downloads. This requires downloading from - * at least one directory authority. */ - public void setIncludeCurrentVote(String fingerprint); - - /* Include the current network status votes published by the given - * directory authorities in the downloads. This requires downloading - * from at least one directory authority. */ - public void setIncludeCurrentVotes(Set<String> fingerprints); - - /* Include all server descriptors referenced from a previously - * downloaded network status consensus in the downloads. */ - public void setIncludeReferencedServerDescriptors(); - - /* Exclude the server descriptor with the given identifier from the - * downloads even if it's referenced from a consensus and we're supposed - * to download all referenced server descriptors. */ - public void setExcludeServerDescriptor(String identifier); - - /* Exclude the server descriptors with the given identifiers from the - * downloads even if they are referenced from a consensus and we're - * supposed to download all referenced server descriptors. */ - public void setExcludeServerDescriptors(Set<String> identifier); - - /* Include all extra-info descriptors referenced from previously - * downloaded server descriptors in the downloads. */ - public void setIncludeReferencedExtraInfoDescriptors(); - - /* Exclude the extra-info descriptor with the given identifier from the - * downloads even if it's referenced from a server descriptor and we're - * supposed to download all referenced extra-info descriptors. */ - public void setExcludeExtraInfoDescriptor(String identifier); - - /* Exclude the extra-info descriptors with the given identifiers from - * the downloads even if they are referenced from server descriptors - * and we're supposed to download all referenced extra-info - * descriptors. */ - public void setExcludeExtraInfoDescriptors(Set<String> identifiers); - - /* Define a connect timeout for a single request. If a timeout expires, - * no further requests will be sent to the directory authority or - * mirror. Setting this value to 0 disables the connect timeout. - * Default value is 1 minute (60 * 1000). */ - public void setConnectTimeout(long connectTimeoutMillis); - - /* Define a read timeout for a single request. If a timeout expires, - * no further requests will be sent to the directory authority or - * mirror. Setting this value to 0 disables the read timeout. - * Default value is 1 minute (60 * 1000). */ - public void setReadTimeout(long readTimeoutMillis); - - /* Define a global timeout for all requests. Once this timeout expires, - * all running requests are aborted and no further requests are made. - * Setting this value to 0 disables the global timeout. Default is 1 - * hour (60 * 60 * 1000). */ - public void setGlobalTimeout(long globalTimeoutMillis); - - /* Fail descriptor parsing when encountering an unrecognized line. This - * is not set by default, because the Tor specifications allow for new - * lines to be added that shall be ignored by older Tor versions. But - * some applications may want to handle unrecognized descriptor lines - * explicitly. */ - public void setFailUnrecognizedDescriptorLines(); - - /* Download the previously configured relay descriptors and make them - * available via the returned blocking iterator. Whenever the - * downloader runs out of descriptors and expects to provide more - * shortly after, it blocks the caller. This method can only be run - * once. */ - public Iterator<DescriptorRequest> downloadDescriptors(); -} - diff --git a/src/org/torproject/descriptor/RelayDescriptorReader.java b/src/org/torproject/descriptor/RelayDescriptorReader.java deleted file mode 100644 index 142f79c..0000000 --- a/src/org/torproject/descriptor/RelayDescriptorReader.java +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright 2011, 2012 The Tor Project - * See LICENSE for licensing information */ -package org.torproject.descriptor; - -import java.io.File; -import java.util.Iterator; - -/* Read relay descriptors from one or more local directories. */ -public interface RelayDescriptorReader { - - /* Add a local directory to read relay descriptors from. */ - public void addDirectory(File directory); - - /* Exclude files that are contained in the given history file and that - * haven't changed since they were last read. Add reads from the - * current run to the history file. Remove files that don't exist - * anymore from the history file. Lines in the history file contain the - * last modified timestamp and the absolute path of a file. */ - public void setExcludeFiles(File historyFile); - - /* Fail descriptor parsing when encountering an unrecognized line. This - * is not set by default, because the Tor specifications allow for new - * lines to be added that shall be ignored by older Tor versions. But - * some applications may want to handle unrecognized descriptor lines - * explicitly. */ - public void setFailUnrecognizedDescriptorLines(); - - /* Read the previously configured relay descriptors and make them - * available via the returned blocking iterator. Whenever the reader - * runs out of descriptors and expects to provide more shortly after, it - * blocks the caller. This method can only be run once. */ - public Iterator<DescriptorFile> readDescriptors(); - -} - diff --git a/src/org/torproject/descriptor/impl/DescriptorDownloaderImpl.java b/src/org/torproject/descriptor/impl/DescriptorDownloaderImpl.java new file mode 100644 index 0000000..3c093d1 --- /dev/null +++ b/src/org/torproject/descriptor/impl/DescriptorDownloaderImpl.java @@ -0,0 +1,265 @@ +/* Copyright 2011, 2012 The Tor Project + * See LICENSE for licensing information */ +package org.torproject.descriptor.impl; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.torproject.descriptor.DescriptorRequest; +import org.torproject.descriptor.DescriptorDownloader; + +public class DescriptorDownloaderImpl + implements DescriptorDownloader { + + private boolean hasStartedDownloading = false; + + private SortedMap<String, DirectoryDownloader> directoryAuthorities = + new TreeMap<String, DirectoryDownloader>(); + public void addDirectoryAuthority(String nickname, String ip, + int dirPort) { + if (this.hasStartedDownloading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to download."); + } + this.checkDirectoryParameters(nickname, ip, dirPort); + DirectoryDownloader directoryAuthority = new DirectoryDownloader( + nickname, ip, dirPort); + this.directoryAuthorities.put(nickname, directoryAuthority); + } + + private SortedMap<String, DirectoryDownloader> directoryMirrors = + new TreeMap<String, DirectoryDownloader>(); + public void addDirectoryMirror(String nickname, String ip, + int dirPort) { + if (this.hasStartedDownloading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to download."); + } + this.checkDirectoryParameters(nickname, ip, dirPort); + DirectoryDownloader directoryMirror = new DirectoryDownloader( + nickname, ip, dirPort); + this.directoryMirrors.put(nickname, directoryMirror); + /* TODO Implement prioritizing mirrors for non-vote downloads. */ + throw new UnsupportedOperationException("Prioritizing directory " + + "mirrors over directory authorities is not implemented yet. " + + "Until it is, configuring directory mirrors is misleading and " + + "therefore not supported."); + } + + private void checkDirectoryParameters(String nickname, String ip, + int dirPort) { + if (nickname == null || nickname.length() < 1) { + throw new IllegalArgumentException("'" + nickname + "' is not a " + + "valid nickname."); + } + if (ip == null || ip.length() < 7 || ip.split("\.").length != 4) { + throw new IllegalArgumentException("'" + ip + "' is not a valid IP " + + "address."); + } + if (dirPort < 1 || dirPort > 65535) { + throw new IllegalArgumentException(String.valueOf(dirPort) + " is " + + "not a valid DirPort."); + } + /* TODO Relax the requirement for directory nicknames to be unique. + * In theory, we can identify them by ip+port. */ + if (this.directoryAuthorities.containsKey(nickname) || + this.directoryMirrors.containsKey(nickname)) { + throw new IllegalArgumentException("Directory nicknames must be " + + "unique."); + } + } + + private boolean downloadConsensus = false; + public void setIncludeCurrentConsensus() { + if (this.hasStartedDownloading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to download."); + } + this.downloadConsensus = true; + } + + private boolean downloadConsensusFromAllAuthorities = false; + public void setIncludeCurrentConsensusFromAllDirectoryAuthorities() { + if (this.hasStartedDownloading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to download."); + } + this.downloadConsensusFromAllAuthorities = true; + } + + private boolean includeCurrentReferencedVotes = false; + public void setIncludeCurrentReferencedVotes() { + if (this.hasStartedDownloading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to download."); + } + this.includeCurrentReferencedVotes = true; + } + + private Set<String> downloadVotes = new HashSet<String>(); + public void setIncludeCurrentVote(String fingerprint) { + if (this.hasStartedDownloading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to download."); + } + this.checkVoteFingerprint(fingerprint); + this.downloadVotes.add(fingerprint); + } + + public void setIncludeCurrentVotes(Set<String> fingerprints) { + if (this.hasStartedDownloading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to download."); + } + if (fingerprints == null) { + throw new IllegalArgumentException("Set of fingerprints must not " + + "be null."); + } + for (String fingerprint : fingerprints) { + this.checkVoteFingerprint(fingerprint); + } + for (String fingerprint : fingerprints) { + this.setIncludeCurrentVote(fingerprint); + } + } + + private void checkVoteFingerprint(String fingerprint) { + if (fingerprint == null || fingerprint.length() != 40) { + throw new IllegalArgumentException("'" + fingerprint + "' is not a " + + "valid fingerprint."); + } + } + + public void setIncludeReferencedServerDescriptors() { + if (this.hasStartedDownloading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to download."); + } + /* TODO Implement me. */ + throw new UnsupportedOperationException("Downloading server " + + "descriptors is not implemented yet."); + } + + public void setExcludeServerDescriptor(String identifier) { + if (this.hasStartedDownloading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to download."); + } + /* TODO Implement me. */ + throw new UnsupportedOperationException("Downloading server " + + "descriptors is not implemented yet."); + } + + public void setExcludeServerDescriptors(Set<String> identifier) { + if (this.hasStartedDownloading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to download."); + } + /* TODO Implement me. */ + throw new UnsupportedOperationException("Downloading server " + + "descriptors is not implemented yet."); + } + + public void setIncludeReferencedExtraInfoDescriptors() { + if (this.hasStartedDownloading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to download."); + } + /* TODO Implement me. */ + throw new UnsupportedOperationException("Downloading extra-info " + + "descriptors is not implemented yet."); + } + + public void setExcludeExtraInfoDescriptor(String identifier) { + if (this.hasStartedDownloading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to download."); + } + /* TODO Implement me. */ + throw new UnsupportedOperationException("Downloading extra-info " + + "descriptors is not implemented yet."); + } + + public void setExcludeExtraInfoDescriptors(Set<String> identifiers) { + if (this.hasStartedDownloading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to download."); + } + /* TODO Implement me. */ + throw new UnsupportedOperationException("Downloading extra-info " + + "descriptors is not implemented yet."); + } + + private long readTimeoutMillis = 60L * 1000L; + public void setReadTimeout(long readTimeoutMillis) { + if (this.hasStartedDownloading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to download."); + } + if (readTimeoutMillis < 0L) { + throw new IllegalArgumentException("Read timeout value " + + String.valueOf(readTimeoutMillis) + " may not be " + + "negative."); + } + this.readTimeoutMillis = readTimeoutMillis; + } + + private long connectTimeoutMillis = 60L * 1000L; + public void setConnectTimeout(long connectTimeoutMillis) { + if (this.hasStartedDownloading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to download."); + } + if (connectTimeoutMillis < 0L) { + throw new IllegalArgumentException("Connect timeout value " + + String.valueOf(connectTimeoutMillis) + " may not be " + + "negative."); + } + this.connectTimeoutMillis = connectTimeoutMillis; + } + + private long globalTimeoutMillis = 60L * 60L * 1000L; + public void setGlobalTimeout(long globalTimeoutMillis) { + if (this.hasStartedDownloading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to download."); + } + if (globalTimeoutMillis < 0L) { + throw new IllegalArgumentException("Global timeout value " + + String.valueOf(globalTimeoutMillis) + " may not be " + + "negative."); + } + this.globalTimeoutMillis = globalTimeoutMillis; + } + + private boolean failUnrecognizedDescriptorLines = false; + public void setFailUnrecognizedDescriptorLines() { + if (this.hasStartedDownloading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to download."); + } + this.failUnrecognizedDescriptorLines = true; + } + + public Iterator<DescriptorRequest> downloadDescriptors() { + if (this.hasStartedDownloading) { + throw new IllegalStateException("Initiating downloads is only " + + "permitted once."); + } + this.hasStartedDownloading = true; + DownloadCoordinatorImpl downloadCoordinator = + new DownloadCoordinatorImpl(this.directoryAuthorities, + this.directoryMirrors, this.downloadConsensus, + this.downloadConsensusFromAllAuthorities, this.downloadVotes, + this.includeCurrentReferencedVotes, this.connectTimeoutMillis, + this.readTimeoutMillis, this.globalTimeoutMillis, + this.failUnrecognizedDescriptorLines); + Iterator<DescriptorRequest> descriptorQueue = downloadCoordinator. + getDescriptorQueue(); + return descriptorQueue; + } +} + diff --git a/src/org/torproject/descriptor/impl/DescriptorReaderImpl.java b/src/org/torproject/descriptor/impl/DescriptorReaderImpl.java new file mode 100644 index 0000000..c22cbe8 --- /dev/null +++ b/src/org/torproject/descriptor/impl/DescriptorReaderImpl.java @@ -0,0 +1,194 @@ +/* Copyright 2011, 2012 The Tor Project + * See LICENSE for licensing information */ +package org.torproject.descriptor.impl; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.Stack; +import java.util.TreeMap; + +import org.torproject.descriptor.Descriptor; +import org.torproject.descriptor.DescriptorFile; +import org.torproject.descriptor.DescriptorReader; + +public class DescriptorReaderImpl implements DescriptorReader { + + private boolean hasStartedReading = false; + + private List<File> directories = new ArrayList<File>(); + public void addDirectory(File directory) { + if (this.hasStartedReading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to read."); + } + this.directories.add(directory); + } + + private File historyFile; + public void setExcludeFiles(File historyFile) { + if (this.hasStartedReading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to read."); + } + this.historyFile = historyFile; + } + + private boolean failUnrecognizedDescriptorLines = false; + public void setFailUnrecognizedDescriptorLines() { + if (this.hasStartedReading) { + throw new IllegalStateException("Reconfiguration is not permitted " + + "after starting to read."); + } + this.failUnrecognizedDescriptorLines = true; + } + + public Iterator<DescriptorFile> readDescriptors() { + if (this.hasStartedReading) { + throw new IllegalStateException("Initiating reading is only " + + "permitted once."); + } + this.hasStartedReading = true; + BlockingIteratorImpl<DescriptorFile> descriptorQueue = + new BlockingIteratorImpl<DescriptorFile>(); + DescriptorReaderRunnable reader = new DescriptorReaderRunnable( + this.directories, descriptorQueue, this.historyFile, + this.failUnrecognizedDescriptorLines); + new Thread(reader).start(); + return descriptorQueue; + } + + private static class DescriptorReaderRunnable implements Runnable { + private List<File> directories; + private BlockingIteratorImpl<DescriptorFile> descriptorQueue; + private File historyFile; + private boolean failUnrecognizedDescriptorLines; + private DescriptorReaderRunnable(List<File> directories, + BlockingIteratorImpl<DescriptorFile> descriptorQueue, + File historyFile, boolean failUnrecognizedDescriptorLines) { + this.directories = directories; + this.descriptorQueue = descriptorQueue; + this.historyFile = historyFile; + this.failUnrecognizedDescriptorLines = + failUnrecognizedDescriptorLines; + } + public void run() { + this.readOldHistory(); + this.readDescriptors(); + this.writeNewHistory(); + } + private SortedMap<String, Long> + oldHistory = new TreeMap<String, Long>(), + newHistory = new TreeMap<String, Long>(); + private void readOldHistory() { + if (this.historyFile == null) { + return; + } + try { + BufferedReader br = new BufferedReader(new FileReader( + this.historyFile)); + String line; + while ((line = br.readLine()) != null) { + if (!line.contains(" ")) { + /* TODO Handle this problem? */ + continue; + } + long lastModifiedMillis = Long.parseLong(line.substring(0, + line.indexOf(" "))); + String absolutePath = line.substring(line.indexOf(" ") + 1); + this.oldHistory.put(absolutePath, lastModifiedMillis); + } + br.close(); + } catch (IOException e) { + /* TODO Handle this exception. */ + } catch (NumberFormatException e) { + /* TODO Handle this exception. */ + } + } + private void writeNewHistory() { + if (this.historyFile == null) { + return; + } + try { + if (this.historyFile.getParentFile() != null) { + this.historyFile.getParentFile().mkdirs(); + } + BufferedWriter bw = new BufferedWriter(new FileWriter( + this.historyFile)); + for (Map.Entry<String, Long> e : this.newHistory.entrySet()) { + String absolutePath = e.getKey(); + long lastModifiedMillis = e.getValue(); + bw.write(String.valueOf(lastModifiedMillis) + " " + absolutePath + + "\n"); + } + bw.close(); + } catch (IOException e) { + /* TODO Handle this exception. */ + } + } + private void readDescriptors() { + for (File directory : this.directories) { + Stack<File> files = new Stack<File>(); + files.add(directory); + boolean abortReading = false; + while (!abortReading && !files.isEmpty()) { + File file = files.pop(); + if (file.isDirectory()) { + files.addAll(Arrays.asList(file.listFiles())); + } else { + String absolutePath = file.getAbsolutePath(); + long lastModifiedMillis = file.lastModified(); + this.newHistory.put(absolutePath, lastModifiedMillis); + if (this.oldHistory.containsKey(absolutePath) && + this.oldHistory.get(absolutePath) == lastModifiedMillis) { + continue; + } + DescriptorFileImpl descriptorFile = new DescriptorFileImpl(); + try { + descriptorFile.setDirectory(directory); + descriptorFile.setFile(file); + descriptorFile.setLastModified(lastModifiedMillis); + descriptorFile.setDescriptors(this.readFile(file)); + } catch (DescriptorParseException e) { + descriptorFile.setException(e); + } catch (IOException e) { + descriptorFile.setException(e); + abortReading = true; + } + this.descriptorQueue.add(descriptorFile); + } + } + } + this.descriptorQueue.setOutOfDescriptors(); + } + private List<Descriptor> readFile(File file) throws IOException, + DescriptorParseException { + FileInputStream fis = new FileInputStream(file); + BufferedInputStream bis = new BufferedInputStream(fis); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int len; + byte[] data = new byte[1024]; + while ((len = bis.read(data, 0, 1024)) >= 0) { + baos.write(data, 0, len); + } + bis.close(); + byte[] rawDescriptorBytes = baos.toByteArray(); + return DescriptorImpl.parseRelayOrBridgeDescriptors( + rawDescriptorBytes, file.getName(), + this.failUnrecognizedDescriptorLines); + } + } +} + diff --git a/src/org/torproject/descriptor/impl/RelayDescriptorDownloaderImpl.java b/src/org/torproject/descriptor/impl/RelayDescriptorDownloaderImpl.java deleted file mode 100644 index 6993509..0000000 --- a/src/org/torproject/descriptor/impl/RelayDescriptorDownloaderImpl.java +++ /dev/null @@ -1,265 +0,0 @@ -/* Copyright 2011, 2012 The Tor Project - * See LICENSE for licensing information */ -package org.torproject.descriptor.impl; - -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; -import java.util.SortedMap; -import java.util.TreeMap; - -import org.torproject.descriptor.DescriptorRequest; -import org.torproject.descriptor.RelayDescriptorDownloader; - -public class RelayDescriptorDownloaderImpl - implements RelayDescriptorDownloader { - - private boolean hasStartedDownloading = false; - - private SortedMap<String, DirectoryDownloader> directoryAuthorities = - new TreeMap<String, DirectoryDownloader>(); - public void addDirectoryAuthority(String nickname, String ip, - int dirPort) { - if (this.hasStartedDownloading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to download."); - } - this.checkDirectoryParameters(nickname, ip, dirPort); - DirectoryDownloader directoryAuthority = new DirectoryDownloader( - nickname, ip, dirPort); - this.directoryAuthorities.put(nickname, directoryAuthority); - } - - private SortedMap<String, DirectoryDownloader> directoryMirrors = - new TreeMap<String, DirectoryDownloader>(); - public void addDirectoryMirror(String nickname, String ip, - int dirPort) { - if (this.hasStartedDownloading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to download."); - } - this.checkDirectoryParameters(nickname, ip, dirPort); - DirectoryDownloader directoryMirror = new DirectoryDownloader( - nickname, ip, dirPort); - this.directoryMirrors.put(nickname, directoryMirror); - /* TODO Implement prioritizing mirrors for non-vote downloads. */ - throw new UnsupportedOperationException("Prioritizing directory " - + "mirrors over directory authorities is not implemented yet. " - + "Until it is, configuring directory mirrors is misleading and " - + "therefore not supported."); - } - - private void checkDirectoryParameters(String nickname, String ip, - int dirPort) { - if (nickname == null || nickname.length() < 1) { - throw new IllegalArgumentException("'" + nickname + "' is not a " - + "valid nickname."); - } - if (ip == null || ip.length() < 7 || ip.split("\.").length != 4) { - throw new IllegalArgumentException("'" + ip + "' is not a valid IP " - + "address."); - } - if (dirPort < 1 || dirPort > 65535) { - throw new IllegalArgumentException(String.valueOf(dirPort) + " is " - + "not a valid DirPort."); - } - /* TODO Relax the requirement for directory nicknames to be unique. - * In theory, we can identify them by ip+port. */ - if (this.directoryAuthorities.containsKey(nickname) || - this.directoryMirrors.containsKey(nickname)) { - throw new IllegalArgumentException("Directory nicknames must be " - + "unique."); - } - } - - private boolean downloadConsensus = false; - public void setIncludeCurrentConsensus() { - if (this.hasStartedDownloading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to download."); - } - this.downloadConsensus = true; - } - - private boolean downloadConsensusFromAllAuthorities = false; - public void setIncludeCurrentConsensusFromAllDirectoryAuthorities() { - if (this.hasStartedDownloading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to download."); - } - this.downloadConsensusFromAllAuthorities = true; - } - - private boolean includeCurrentReferencedVotes = false; - public void setIncludeCurrentReferencedVotes() { - if (this.hasStartedDownloading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to download."); - } - this.includeCurrentReferencedVotes = true; - } - - private Set<String> downloadVotes = new HashSet<String>(); - public void setIncludeCurrentVote(String fingerprint) { - if (this.hasStartedDownloading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to download."); - } - this.checkVoteFingerprint(fingerprint); - this.downloadVotes.add(fingerprint); - } - - public void setIncludeCurrentVotes(Set<String> fingerprints) { - if (this.hasStartedDownloading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to download."); - } - if (fingerprints == null) { - throw new IllegalArgumentException("Set of fingerprints must not " - + "be null."); - } - for (String fingerprint : fingerprints) { - this.checkVoteFingerprint(fingerprint); - } - for (String fingerprint : fingerprints) { - this.setIncludeCurrentVote(fingerprint); - } - } - - private void checkVoteFingerprint(String fingerprint) { - if (fingerprint == null || fingerprint.length() != 40) { - throw new IllegalArgumentException("'" + fingerprint + "' is not a " - + "valid fingerprint."); - } - } - - public void setIncludeReferencedServerDescriptors() { - if (this.hasStartedDownloading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to download."); - } - /* TODO Implement me. */ - throw new UnsupportedOperationException("Downloading server " - + "descriptors is not implemented yet."); - } - - public void setExcludeServerDescriptor(String identifier) { - if (this.hasStartedDownloading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to download."); - } - /* TODO Implement me. */ - throw new UnsupportedOperationException("Downloading server " - + "descriptors is not implemented yet."); - } - - public void setExcludeServerDescriptors(Set<String> identifier) { - if (this.hasStartedDownloading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to download."); - } - /* TODO Implement me. */ - throw new UnsupportedOperationException("Downloading server " - + "descriptors is not implemented yet."); - } - - public void setIncludeReferencedExtraInfoDescriptors() { - if (this.hasStartedDownloading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to download."); - } - /* TODO Implement me. */ - throw new UnsupportedOperationException("Downloading extra-info " - + "descriptors is not implemented yet."); - } - - public void setExcludeExtraInfoDescriptor(String identifier) { - if (this.hasStartedDownloading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to download."); - } - /* TODO Implement me. */ - throw new UnsupportedOperationException("Downloading extra-info " - + "descriptors is not implemented yet."); - } - - public void setExcludeExtraInfoDescriptors(Set<String> identifiers) { - if (this.hasStartedDownloading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to download."); - } - /* TODO Implement me. */ - throw new UnsupportedOperationException("Downloading extra-info " - + "descriptors is not implemented yet."); - } - - private long readTimeoutMillis = 60L * 1000L; - public void setReadTimeout(long readTimeoutMillis) { - if (this.hasStartedDownloading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to download."); - } - if (readTimeoutMillis < 0L) { - throw new IllegalArgumentException("Read timeout value " - + String.valueOf(readTimeoutMillis) + " may not be " - + "negative."); - } - this.readTimeoutMillis = readTimeoutMillis; - } - - private long connectTimeoutMillis = 60L * 1000L; - public void setConnectTimeout(long connectTimeoutMillis) { - if (this.hasStartedDownloading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to download."); - } - if (connectTimeoutMillis < 0L) { - throw new IllegalArgumentException("Connect timeout value " - + String.valueOf(connectTimeoutMillis) + " may not be " - + "negative."); - } - this.connectTimeoutMillis = connectTimeoutMillis; - } - - private long globalTimeoutMillis = 60L * 60L * 1000L; - public void setGlobalTimeout(long globalTimeoutMillis) { - if (this.hasStartedDownloading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to download."); - } - if (globalTimeoutMillis < 0L) { - throw new IllegalArgumentException("Global timeout value " - + String.valueOf(globalTimeoutMillis) + " may not be " - + "negative."); - } - this.globalTimeoutMillis = globalTimeoutMillis; - } - - private boolean failUnrecognizedDescriptorLines = false; - public void setFailUnrecognizedDescriptorLines() { - if (this.hasStartedDownloading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to download."); - } - this.failUnrecognizedDescriptorLines = true; - } - - public Iterator<DescriptorRequest> downloadDescriptors() { - if (this.hasStartedDownloading) { - throw new IllegalStateException("Initiating downloads is only " - + "permitted once."); - } - this.hasStartedDownloading = true; - DownloadCoordinatorImpl downloadCoordinator = - new DownloadCoordinatorImpl(this.directoryAuthorities, - this.directoryMirrors, this.downloadConsensus, - this.downloadConsensusFromAllAuthorities, this.downloadVotes, - this.includeCurrentReferencedVotes, this.connectTimeoutMillis, - this.readTimeoutMillis, this.globalTimeoutMillis, - this.failUnrecognizedDescriptorLines); - Iterator<DescriptorRequest> descriptorQueue = downloadCoordinator. - getDescriptorQueue(); - return descriptorQueue; - } -} - diff --git a/src/org/torproject/descriptor/impl/RelayOrBridgeDescriptorReaderImpl.java b/src/org/torproject/descriptor/impl/RelayOrBridgeDescriptorReaderImpl.java deleted file mode 100644 index 60c1e36..0000000 --- a/src/org/torproject/descriptor/impl/RelayOrBridgeDescriptorReaderImpl.java +++ /dev/null @@ -1,198 +0,0 @@ -/* Copyright 2011, 2012 The Tor Project - * See LICENSE for licensing information */ -package org.torproject.descriptor.impl; - -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.SortedMap; -import java.util.Stack; -import java.util.TreeMap; - -import org.torproject.descriptor.BridgeDescriptorReader; -import org.torproject.descriptor.BridgePoolAssignmentReader; -import org.torproject.descriptor.Descriptor; -import org.torproject.descriptor.DescriptorFile; -import org.torproject.descriptor.RelayDescriptorReader; - -public class RelayOrBridgeDescriptorReaderImpl - implements RelayDescriptorReader, BridgeDescriptorReader, - BridgePoolAssignmentReader { - - private boolean hasStartedReading = false; - - private List<File> directories = new ArrayList<File>(); - public void addDirectory(File directory) { - if (this.hasStartedReading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to read."); - } - this.directories.add(directory); - } - - private File historyFile; - public void setExcludeFiles(File historyFile) { - if (this.hasStartedReading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to read."); - } - this.historyFile = historyFile; - } - - private boolean failUnrecognizedDescriptorLines = false; - public void setFailUnrecognizedDescriptorLines() { - if (this.hasStartedReading) { - throw new IllegalStateException("Reconfiguration is not permitted " - + "after starting to read."); - } - this.failUnrecognizedDescriptorLines = true; - } - - public Iterator<DescriptorFile> readDescriptors() { - if (this.hasStartedReading) { - throw new IllegalStateException("Initiating reading is only " - + "permitted once."); - } - this.hasStartedReading = true; - BlockingIteratorImpl<DescriptorFile> descriptorQueue = - new BlockingIteratorImpl<DescriptorFile>(); - DescriptorReader reader = new DescriptorReader(this.directories, - descriptorQueue, this.historyFile, - this.failUnrecognizedDescriptorLines); - new Thread(reader).start(); - return descriptorQueue; - } - - private static class DescriptorReader implements Runnable { - private List<File> directories; - private BlockingIteratorImpl<DescriptorFile> descriptorQueue; - private File historyFile; - private boolean failUnrecognizedDescriptorLines; - private DescriptorReader(List<File> directories, - BlockingIteratorImpl<DescriptorFile> descriptorQueue, - File historyFile, boolean failUnrecognizedDescriptorLines) { - this.directories = directories; - this.descriptorQueue = descriptorQueue; - this.historyFile = historyFile; - this.failUnrecognizedDescriptorLines = - failUnrecognizedDescriptorLines; - } - public void run() { - this.readOldHistory(); - this.readDescriptors(); - this.writeNewHistory(); - } - private SortedMap<String, Long> - oldHistory = new TreeMap<String, Long>(), - newHistory = new TreeMap<String, Long>(); - private void readOldHistory() { - if (this.historyFile == null) { - return; - } - try { - BufferedReader br = new BufferedReader(new FileReader( - this.historyFile)); - String line; - while ((line = br.readLine()) != null) { - if (!line.contains(" ")) { - /* TODO Handle this problem? */ - continue; - } - long lastModifiedMillis = Long.parseLong(line.substring(0, - line.indexOf(" "))); - String absolutePath = line.substring(line.indexOf(" ") + 1); - this.oldHistory.put(absolutePath, lastModifiedMillis); - } - br.close(); - } catch (IOException e) { - /* TODO Handle this exception. */ - } catch (NumberFormatException e) { - /* TODO Handle this exception. */ - } - } - private void writeNewHistory() { - if (this.historyFile == null) { - return; - } - try { - if (this.historyFile.getParentFile() != null) { - this.historyFile.getParentFile().mkdirs(); - } - BufferedWriter bw = new BufferedWriter(new FileWriter( - this.historyFile)); - for (Map.Entry<String, Long> e : this.newHistory.entrySet()) { - String absolutePath = e.getKey(); - long lastModifiedMillis = e.getValue(); - bw.write(String.valueOf(lastModifiedMillis) + " " + absolutePath - + "\n"); - } - bw.close(); - } catch (IOException e) { - /* TODO Handle this exception. */ - } - } - private void readDescriptors() { - for (File directory : this.directories) { - Stack<File> files = new Stack<File>(); - files.add(directory); - boolean abortReading = false; - while (!abortReading && !files.isEmpty()) { - File file = files.pop(); - if (file.isDirectory()) { - files.addAll(Arrays.asList(file.listFiles())); - } else { - String absolutePath = file.getAbsolutePath(); - long lastModifiedMillis = file.lastModified(); - this.newHistory.put(absolutePath, lastModifiedMillis); - if (this.oldHistory.containsKey(absolutePath) && - this.oldHistory.get(absolutePath) == lastModifiedMillis) { - continue; - } - DescriptorFileImpl descriptorFile = new DescriptorFileImpl(); - try { - descriptorFile.setDirectory(directory); - descriptorFile.setFile(file); - descriptorFile.setLastModified(lastModifiedMillis); - descriptorFile.setDescriptors(this.readFile(file)); - } catch (DescriptorParseException e) { - descriptorFile.setException(e); - } catch (IOException e) { - descriptorFile.setException(e); - abortReading = true; - } - this.descriptorQueue.add(descriptorFile); - } - } - } - this.descriptorQueue.setOutOfDescriptors(); - } - private List<Descriptor> readFile(File file) throws IOException, - DescriptorParseException { - FileInputStream fis = new FileInputStream(file); - BufferedInputStream bis = new BufferedInputStream(fis); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - int len; - byte[] data = new byte[1024]; - while ((len = bis.read(data, 0, 1024)) >= 0) { - baos.write(data, 0, len); - } - bis.close(); - byte[] rawDescriptorBytes = baos.toByteArray(); - return DescriptorImpl.parseRelayOrBridgeDescriptors( - rawDescriptorBytes, file.getName(), - this.failUnrecognizedDescriptorLines); - } - } -} -
tor-commits@lists.torproject.org