mirror of
https://github.com/torproject/collector.git
synced 2024-11-23 17:39:45 +00:00
Resolve a bunch of checkstyle warnings.
This commit is contained in:
parent
b41a71cd70
commit
8bd642198c
@ -5,7 +5,11 @@
|
|||||||
|
|
||||||
<!--
|
<!--
|
||||||
Checkstyle configuration that checks the Google coding conventions from Google Java Style
|
Checkstyle configuration that checks the Google coding conventions from Google Java Style
|
||||||
that can be found at https://google.github.io/styleguide/javaguide.html.
|
that can be found at https://google.github.io/styleguide/javaguide.html with the following
|
||||||
|
modifications:
|
||||||
|
|
||||||
|
- Replaced com.google with org.torproject in import statement ordering
|
||||||
|
[CustomImportOrder].
|
||||||
|
|
||||||
Checkstyle is very configurable. Be sure to read the documentation at
|
Checkstyle is very configurable. Be sure to read the documentation at
|
||||||
http://checkstyle.sf.net (or in your downloaded distribution).
|
http://checkstyle.sf.net (or in your downloaded distribution).
|
||||||
@ -159,7 +163,7 @@
|
|||||||
<module name="OverloadMethodsDeclarationOrder"/>
|
<module name="OverloadMethodsDeclarationOrder"/>
|
||||||
<module name="VariableDeclarationUsageDistance"/>
|
<module name="VariableDeclarationUsageDistance"/>
|
||||||
<module name="CustomImportOrder">
|
<module name="CustomImportOrder">
|
||||||
<property name="specialImportsRegExp" value="com.google"/>
|
<property name="specialImportsRegExp" value="org.torproject"/>
|
||||||
<property name="sortImportsInGroupAlphabetically" value="true"/>
|
<property name="sortImportsInGroupAlphabetically" value="true"/>
|
||||||
<property name="customImportOrderRules" value="STATIC###SPECIAL_IMPORTS###THIRD_PARTY_PACKAGE###STANDARD_JAVA_PACKAGE"/>
|
<property name="customImportOrderRules" value="STATIC###SPECIAL_IMPORTS###THIRD_PARTY_PACKAGE###STANDARD_JAVA_PACKAGE"/>
|
||||||
</module>
|
</module>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* Copyright 2010--2012 The Tor Project
|
/* Copyright 2010--2016 The Tor Project
|
||||||
* See LICENSE for licensing information */
|
* See LICENSE for licensing information */
|
||||||
|
|
||||||
package org.torproject.collector.bridgedescs;
|
package org.torproject.collector.bridgedescs;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
@ -9,13 +10,17 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class BridgeDescriptorParser {
|
public class BridgeDescriptorParser {
|
||||||
|
|
||||||
private SanitizedBridgesWriter sbw;
|
private SanitizedBridgesWriter sbw;
|
||||||
|
|
||||||
private Logger logger;
|
private Logger logger;
|
||||||
|
|
||||||
public BridgeDescriptorParser(SanitizedBridgesWriter sbw) {
|
public BridgeDescriptorParser(SanitizedBridgesWriter sbw) {
|
||||||
this.sbw = sbw;
|
this.sbw = sbw;
|
||||||
this.logger =
|
this.logger =
|
||||||
Logger.getLogger(BridgeDescriptorParser.class.getName());
|
Logger.getLogger(BridgeDescriptorParser.class.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void parse(byte[] allData, String dateTime) {
|
public void parse(byte[] allData, String dateTime) {
|
||||||
try {
|
try {
|
||||||
BufferedReader br = new BufferedReader(new StringReader(
|
BufferedReader br = new BufferedReader(new StringReader(
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
/* Copyright 2010--2012 The Tor Project
|
/* Copyright 2010--2016 The Tor Project
|
||||||
* See LICENSE for licensing information */
|
* See LICENSE for licensing information */
|
||||||
|
|
||||||
package org.torproject.collector.bridgedescs;
|
package org.torproject.collector.bridgedescs;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Hex;
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
|
||||||
|
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
@ -20,11 +26,6 @@ import java.util.TreeSet;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Hex;
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
|
||||||
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
|
|
||||||
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the half-hourly snapshots of bridge descriptors from Tonga.
|
* Reads the half-hourly snapshots of bridge descriptors from Tonga.
|
||||||
*/
|
*/
|
||||||
@ -32,8 +33,8 @@ public class BridgeSnapshotReader {
|
|||||||
public BridgeSnapshotReader(BridgeDescriptorParser bdp,
|
public BridgeSnapshotReader(BridgeDescriptorParser bdp,
|
||||||
File bridgeDirectoriesDir, File statsDirectory) {
|
File bridgeDirectoriesDir, File statsDirectory) {
|
||||||
|
|
||||||
if (bdp == null || bridgeDirectoriesDir == null ||
|
if (bdp == null || bridgeDirectoriesDir == null
|
||||||
statsDirectory == null) {
|
|| statsDirectory == null) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,11 +63,15 @@ public class BridgeSnapshotReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.fine("Importing files in directory " + bridgeDirectoriesDir
|
logger.fine("Importing files in directory " + bridgeDirectoriesDir
|
||||||
+ "/...");
|
+ "/...");
|
||||||
Set<String> descriptorImportHistory = new HashSet<String>();
|
Set<String> descriptorImportHistory = new HashSet<String>();
|
||||||
int parsedFiles = 0, skippedFiles = 0, parsedStatuses = 0,
|
int parsedFiles = 0;
|
||||||
parsedServerDescriptors = 0, skippedServerDescriptors = 0,
|
int skippedFiles = 0;
|
||||||
parsedExtraInfoDescriptors = 0, skippedExtraInfoDescriptors = 0;
|
int parsedStatuses = 0;
|
||||||
|
int parsedServerDescriptors = 0;
|
||||||
|
int skippedServerDescriptors = 0;
|
||||||
|
int parsedExtraInfoDescriptors = 0;
|
||||||
|
int skippedExtraInfoDescriptors = 0;
|
||||||
Stack<File> filesInInputDir = new Stack<File>();
|
Stack<File> filesInInputDir = new Stack<File>();
|
||||||
filesInInputDir.add(bdDir);
|
filesInInputDir.add(bdDir);
|
||||||
while (!filesInInputDir.isEmpty()) {
|
while (!filesInInputDir.isEmpty()) {
|
||||||
@ -118,9 +123,9 @@ public class BridgeSnapshotReader {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (firstLine.startsWith("published ") ||
|
if (firstLine.startsWith("published ")
|
||||||
firstLine.startsWith("flag-thresholds ") ||
|
|| firstLine.startsWith("flag-thresholds ")
|
||||||
firstLine.startsWith("r ")) {
|
|| firstLine.startsWith("r ")) {
|
||||||
bdp.parse(allData, dateTime);
|
bdp.parse(allData, dateTime);
|
||||||
parsedStatuses++;
|
parsedStatuses++;
|
||||||
} else if (descriptorImportHistory.contains(fileDigest)) {
|
} else if (descriptorImportHistory.contains(fileDigest)) {
|
||||||
@ -129,10 +134,11 @@ public class BridgeSnapshotReader {
|
|||||||
skippedFiles++;
|
skippedFiles++;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
int start = -1, sig = -1, end = -1;
|
int start = -1;
|
||||||
String startToken =
|
int sig = -1;
|
||||||
firstLine.startsWith("router ") ?
|
int end = -1;
|
||||||
"router " : "extra-info ";
|
String startToken = firstLine.startsWith("router ")
|
||||||
|
? "router " : "extra-info ";
|
||||||
String sigToken = "\nrouter-signature\n";
|
String sigToken = "\nrouter-signature\n";
|
||||||
String endToken = "\n-----END SIGNATURE-----\n";
|
String endToken = "\n-----END SIGNATURE-----\n";
|
||||||
while (end < ascii.length()) {
|
while (end < ascii.length()) {
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
/* Copyright 2010--2016 The Tor Project
|
/* Copyright 2010--2016 The Tor Project
|
||||||
* See LICENSE for licensing information */
|
* See LICENSE for licensing information */
|
||||||
|
|
||||||
package org.torproject.collector.bridgedescs;
|
package org.torproject.collector.bridgedescs;
|
||||||
|
|
||||||
|
import org.torproject.collector.main.Configuration;
|
||||||
|
import org.torproject.collector.main.LockFile;
|
||||||
|
import org.torproject.collector.main.LoggingConfiguration;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.DecoderException;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.commons.codec.binary.Hex;
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -25,14 +35,6 @@ import java.util.TreeMap;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.apache.commons.codec.DecoderException;
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
|
||||||
import org.apache.commons.codec.binary.Hex;
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
|
||||||
import org.torproject.collector.main.Configuration;
|
|
||||||
import org.torproject.collector.main.LockFile;
|
|
||||||
import org.torproject.collector.main.LoggingConfiguration;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sanitizes bridge descriptors, i.e., removes all possibly sensitive
|
* Sanitizes bridge descriptors, i.e., removes all possibly sensitive
|
||||||
* information from them, and writes them to a local directory structure.
|
* information from them, and writes them to a local directory structure.
|
||||||
@ -125,8 +127,8 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
config.getLimitBridgeDescriptorMappings();
|
config.getLimitBridgeDescriptorMappings();
|
||||||
File statsDirectory = new File("stats");
|
File statsDirectory = new File("stats");
|
||||||
|
|
||||||
if (bridgeDirectoriesDirectory == null ||
|
if (bridgeDirectoriesDirectory == null
|
||||||
sanitizedBridgesDirectory == null || statsDirectory == null) {
|
|| sanitizedBridgesDirectory == null || statsDirectory == null) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,9 +171,9 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
String line;
|
String line;
|
||||||
while ((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
String[] parts = line.split(",");
|
String[] parts = line.split(",");
|
||||||
if ((line.length() != ("yyyy-MM,".length() + 31 * 2) &&
|
if ((line.length() != ("yyyy-MM,".length() + 31 * 2)
|
||||||
line.length() != ("yyyy-MM,".length() + 50 * 2)) ||
|
&& line.length() != ("yyyy-MM,".length() + 50 * 2))
|
||||||
parts.length != 2) {
|
|| parts.length != 2) {
|
||||||
this.logger.warning("Invalid line in bridge-ip-secrets file "
|
this.logger.warning("Invalid line in bridge-ip-secrets file "
|
||||||
+ "starting with '" + line.substring(0, 7) + "'! "
|
+ "starting with '" + line.substring(0, 7) + "'! "
|
||||||
+ "Not calculating any IP address hashes in this "
|
+ "Not calculating any IP address hashes in this "
|
||||||
@ -364,8 +366,8 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private byte[] getSecretForMonth(String month) throws IOException {
|
private byte[] getSecretForMonth(String month) throws IOException {
|
||||||
if (!this.secretsForHashingIPAddresses.containsKey(month) ||
|
if (!this.secretsForHashingIPAddresses.containsKey(month)
|
||||||
this.secretsForHashingIPAddresses.get(month).length == 31) {
|
|| this.secretsForHashingIPAddresses.get(month).length == 31) {
|
||||||
byte[] secret = new byte[50];
|
byte[] secret = new byte[50];
|
||||||
this.secureRandom.nextBytes(secret);
|
this.secureRandom.nextBytes(secret);
|
||||||
if (this.secretsForHashingIPAddresses.containsKey(month)) {
|
if (this.secretsForHashingIPAddresses.containsKey(month)) {
|
||||||
@ -420,8 +422,8 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
maxNetworkStatusPublishedTime = publicationTime;
|
maxNetworkStatusPublishedTime = publicationTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.bridgeSanitizingCutOffTimestamp.
|
if (this.bridgeSanitizingCutOffTimestamp
|
||||||
compareTo(publicationTime) > 0) {
|
.compareTo(publicationTime) > 0) {
|
||||||
this.logger.log(!this.haveWarnedAboutInterval ? Level.WARNING
|
this.logger.log(!this.haveWarnedAboutInterval ? Level.WARNING
|
||||||
: Level.FINE, "Sanitizing and storing network status with "
|
: Level.FINE, "Sanitizing and storing network status with "
|
||||||
+ "publication time outside our descriptor sanitizing "
|
+ "publication time outside our descriptor sanitizing "
|
||||||
@ -476,9 +478,9 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
String dirPort = parts[8];
|
String dirPort = parts[8];
|
||||||
|
|
||||||
/* Determine most recent descriptor publication time. */
|
/* Determine most recent descriptor publication time. */
|
||||||
if (descPublicationTime.compareTo(publicationTime) <= 0 &&
|
if (descPublicationTime.compareTo(publicationTime) <= 0
|
||||||
(mostRecentDescPublished == null ||
|
&& (mostRecentDescPublished == null
|
||||||
descPublicationTime.compareTo(
|
|| descPublicationTime.compareTo(
|
||||||
mostRecentDescPublished) > 0)) {
|
mostRecentDescPublished) > 0)) {
|
||||||
mostRecentDescPublished = descPublicationTime;
|
mostRecentDescPublished = descPublicationTime;
|
||||||
}
|
}
|
||||||
@ -515,9 +517,9 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Nothing special about s, w, and p lines; just copy them. */
|
/* Nothing special about s, w, and p lines; just copy them. */
|
||||||
} else if (line.startsWith("s ") || line.equals("s") ||
|
} else if (line.startsWith("s ") || line.equals("s")
|
||||||
line.startsWith("w ") || line.equals("w") ||
|
|| line.startsWith("w ") || line.equals("w")
|
||||||
line.startsWith("p ") || line.equals("p")) {
|
|| line.startsWith("p ") || line.equals("p")) {
|
||||||
scrubbed.append(line + "\n");
|
scrubbed.append(line + "\n");
|
||||||
|
|
||||||
/* There should be nothing else but r, w, p, and s lines in the
|
/* There should be nothing else but r, w, p, and s lines in the
|
||||||
@ -541,9 +543,9 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
SimpleDateFormat formatter = new SimpleDateFormat(
|
SimpleDateFormat formatter = new SimpleDateFormat(
|
||||||
"yyyy-MM-dd HH:mm:ss");
|
"yyyy-MM-dd HH:mm:ss");
|
||||||
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
|
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||||
if (formatter.parse(publicationTime).getTime() -
|
if (formatter.parse(publicationTime).getTime()
|
||||||
formatter.parse(mostRecentDescPublished).getTime() >
|
- formatter.parse(mostRecentDescPublished).getTime()
|
||||||
60L * 60L * 1000L) {
|
> 60L * 60L * 1000L) {
|
||||||
this.logger.warning("The most recent descriptor in the bridge "
|
this.logger.warning("The most recent descriptor in the bridge "
|
||||||
+ "network status published at " + publicationTime + " was "
|
+ "network status published at " + publicationTime + " was "
|
||||||
+ "published at " + mostRecentDescPublished + " which is "
|
+ "published at " + mostRecentDescPublished + " which is "
|
||||||
@ -609,16 +611,21 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parse descriptor to generate a sanitized version. */
|
/* Parse descriptor to generate a sanitized version. */
|
||||||
String scrubbedDesc = null, published = null,
|
String scrubbedDesc = null;
|
||||||
masterKeyEd25519FromIdentityEd25519 = null;
|
String published = null;
|
||||||
|
String masterKeyEd25519FromIdentityEd25519 = null;
|
||||||
try {
|
try {
|
||||||
BufferedReader br = new BufferedReader(new StringReader(
|
BufferedReader br = new BufferedReader(new StringReader(
|
||||||
new String(data, "US-ASCII")));
|
new String(data, "US-ASCII")));
|
||||||
StringBuilder scrubbed = new StringBuilder();
|
StringBuilder scrubbed = new StringBuilder();
|
||||||
String line = null, hashedBridgeIdentity = null, address = null,
|
String line = null;
|
||||||
routerLine = null, scrubbedAddress = null,
|
String hashedBridgeIdentity = null;
|
||||||
masterKeyEd25519 = null;
|
String address = null;
|
||||||
List<String> orAddresses = null, scrubbedOrAddresses = null;
|
String routerLine = null;
|
||||||
|
String scrubbedAddress = null;
|
||||||
|
String masterKeyEd25519 = null;
|
||||||
|
List<String> orAddresses = null;
|
||||||
|
List<String> scrubbedOrAddresses = null;
|
||||||
boolean skipCrypto = false;
|
boolean skipCrypto = false;
|
||||||
while ((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
|
|
||||||
@ -649,8 +656,8 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
if (published.compareTo(maxServerDescriptorPublishedTime) > 0) {
|
if (published.compareTo(maxServerDescriptorPublishedTime) > 0) {
|
||||||
maxServerDescriptorPublishedTime = published;
|
maxServerDescriptorPublishedTime = published;
|
||||||
}
|
}
|
||||||
if (this.bridgeSanitizingCutOffTimestamp.
|
if (this.bridgeSanitizingCutOffTimestamp
|
||||||
compareTo(published) > 0) {
|
.compareTo(published) > 0) {
|
||||||
this.logger.log(!this.haveWarnedAboutInterval
|
this.logger.log(!this.haveWarnedAboutInterval
|
||||||
? Level.WARNING : Level.FINE, "Sanitizing and storing "
|
? Level.WARNING : Level.FINE, "Sanitizing and storing "
|
||||||
+ "server descriptor with publication time outside our "
|
+ "server descriptor with publication time outside our "
|
||||||
@ -661,15 +668,15 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
|
|
||||||
/* Parse the fingerprint to determine the hashed bridge
|
/* Parse the fingerprint to determine the hashed bridge
|
||||||
* identity. */
|
* identity. */
|
||||||
} else if (line.startsWith("opt fingerprint ") ||
|
} else if (line.startsWith("opt fingerprint ")
|
||||||
line.startsWith("fingerprint ")) {
|
|| line.startsWith("fingerprint ")) {
|
||||||
String fingerprint = line.substring(line.startsWith("opt ") ?
|
String fingerprint = line.substring(line.startsWith("opt ")
|
||||||
"opt fingerprint".length() : "fingerprint".length()).
|
? "opt fingerprint".length() : "fingerprint".length())
|
||||||
replaceAll(" ", "").toLowerCase();
|
.replaceAll(" ", "").toLowerCase();
|
||||||
byte[] fingerprintBytes = Hex.decodeHex(
|
byte[] fingerprintBytes = Hex.decodeHex(
|
||||||
fingerprint.toCharArray());
|
fingerprint.toCharArray());
|
||||||
hashedBridgeIdentity = DigestUtils.shaHex(fingerprintBytes).
|
hashedBridgeIdentity = DigestUtils.shaHex(fingerprintBytes)
|
||||||
toLowerCase();
|
.toLowerCase();
|
||||||
try {
|
try {
|
||||||
scrubbedAddress = scrubIpv4Address(address, fingerprintBytes,
|
scrubbedAddress = scrubIpv4Address(address, fingerprintBytes,
|
||||||
published);
|
published);
|
||||||
@ -695,9 +702,10 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
}
|
}
|
||||||
scrubbed.append((line.startsWith("opt ") ? "opt " : "")
|
scrubbed.append((line.startsWith("opt ") ? "opt " : "")
|
||||||
+ "fingerprint");
|
+ "fingerprint");
|
||||||
for (int i = 0; i < hashedBridgeIdentity.length() / 4; i++)
|
for (int i = 0; i < hashedBridgeIdentity.length() / 4; i++) {
|
||||||
scrubbed.append(" " + hashedBridgeIdentity.substring(4 * i,
|
scrubbed.append(" " + hashedBridgeIdentity.substring(4 * i,
|
||||||
4 * (i + 1)).toUpperCase());
|
4 * (i + 1)).toUpperCase());
|
||||||
|
}
|
||||||
scrubbed.append("\n");
|
scrubbed.append("\n");
|
||||||
|
|
||||||
/* Replace the contact line (if present) with a generic one. */
|
/* Replace the contact line (if present) with a generic one. */
|
||||||
@ -722,8 +730,8 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
|
|
||||||
/* Replace extra-info digest with the hashed digest of the
|
/* Replace extra-info digest with the hashed digest of the
|
||||||
* non-scrubbed descriptor. */
|
* non-scrubbed descriptor. */
|
||||||
} else if (line.startsWith("opt extra-info-digest ") ||
|
} else if (line.startsWith("opt extra-info-digest ")
|
||||||
line.startsWith("extra-info-digest ")) {
|
|| line.startsWith("extra-info-digest ")) {
|
||||||
String[] parts = line.split(" ");
|
String[] parts = line.split(" ");
|
||||||
if (line.startsWith("opt ")) {
|
if (line.startsWith("opt ")) {
|
||||||
scrubbed.append("opt ");
|
scrubbed.append("opt ");
|
||||||
@ -733,8 +741,8 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
Hex.decodeHex(parts[1].toCharArray())).toUpperCase());
|
Hex.decodeHex(parts[1].toCharArray())).toUpperCase());
|
||||||
if (parts.length > 2) {
|
if (parts.length > 2) {
|
||||||
scrubbed.append(" " + Base64.encodeBase64String(
|
scrubbed.append(" " + Base64.encodeBase64String(
|
||||||
DigestUtils.sha256(Base64.decodeBase64(parts[2]))).
|
DigestUtils.sha256(Base64.decodeBase64(parts[2])))
|
||||||
replaceAll("=", ""));
|
.replaceAll("=", ""));
|
||||||
}
|
}
|
||||||
scrubbed.append("\n");
|
scrubbed.append("\n");
|
||||||
|
|
||||||
@ -752,8 +760,8 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
/* Extract master-key-ed25519 from identity-ed25519. */
|
/* Extract master-key-ed25519 from identity-ed25519. */
|
||||||
} else if (line.equals("identity-ed25519")) {
|
} else if (line.equals("identity-ed25519")) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
while ((line = br.readLine()) != null &&
|
while ((line = br.readLine()) != null
|
||||||
!line.equals("-----END ED25519 CERT-----")) {
|
&& !line.equals("-----END ED25519 CERT-----")) {
|
||||||
if (line.equals("-----BEGIN ED25519 CERT-----")) {
|
if (line.equals("-----BEGIN ED25519 CERT-----")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -764,8 +772,8 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
sb.toString());
|
sb.toString());
|
||||||
String sha256MasterKeyEd25519 = Base64.encodeBase64String(
|
String sha256MasterKeyEd25519 = Base64.encodeBase64String(
|
||||||
DigestUtils.sha256(Base64.decodeBase64(
|
DigestUtils.sha256(Base64.decodeBase64(
|
||||||
masterKeyEd25519FromIdentityEd25519 + "="))).
|
masterKeyEd25519FromIdentityEd25519 + "=")))
|
||||||
replaceAll("=", "");
|
.replaceAll("=", "");
|
||||||
scrubbed.append("master-key-ed25519 " + sha256MasterKeyEd25519
|
scrubbed.append("master-key-ed25519 " + sha256MasterKeyEd25519
|
||||||
+ "\n");
|
+ "\n");
|
||||||
if (masterKeyEd25519 != null && !masterKeyEd25519.equals(
|
if (masterKeyEd25519 != null && !masterKeyEd25519.equals(
|
||||||
@ -778,8 +786,8 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
/* Verify that identity-ed25519 and master-key-ed25519 match. */
|
/* Verify that identity-ed25519 and master-key-ed25519 match. */
|
||||||
} else if (line.startsWith("master-key-ed25519 ")) {
|
} else if (line.startsWith("master-key-ed25519 ")) {
|
||||||
masterKeyEd25519 = line.substring(line.indexOf(" ") + 1);
|
masterKeyEd25519 = line.substring(line.indexOf(" ") + 1);
|
||||||
if (masterKeyEd25519FromIdentityEd25519 != null &&
|
if (masterKeyEd25519FromIdentityEd25519 != null
|
||||||
!masterKeyEd25519FromIdentityEd25519.equals(
|
&& !masterKeyEd25519FromIdentityEd25519.equals(
|
||||||
masterKeyEd25519)) {
|
masterKeyEd25519)) {
|
||||||
this.logger.warning("Mismatch between identity-ed25519 and "
|
this.logger.warning("Mismatch between identity-ed25519 and "
|
||||||
+ "master-key-ed25519. Skipping.");
|
+ "master-key-ed25519. Skipping.");
|
||||||
@ -829,9 +837,9 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
/* Skip all crypto parts that might leak the bridge's identity
|
/* Skip all crypto parts that might leak the bridge's identity
|
||||||
* fingerprint. */
|
* fingerprint. */
|
||||||
} else if (line.startsWith("-----BEGIN ")
|
} else if (line.startsWith("-----BEGIN ")
|
||||||
|| line.equals("onion-key") || line.equals("signing-key") ||
|
|| line.equals("onion-key") || line.equals("signing-key")
|
||||||
line.equals("onion-key-crosscert") ||
|
|| line.equals("onion-key-crosscert")
|
||||||
line.startsWith("ntor-onion-key-crosscert ")) {
|
|| line.startsWith("ntor-onion-key-crosscert ")) {
|
||||||
skipCrypto = true;
|
skipCrypto = true;
|
||||||
|
|
||||||
/* Stop skipping lines when the crypto parts are over. */
|
/* Stop skipping lines when the crypto parts are over. */
|
||||||
@ -893,8 +901,8 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
byte[] forDigest = new byte[sig - start];
|
byte[] forDigest = new byte[sig - start];
|
||||||
System.arraycopy(data, start, forDigest, 0, sig - start);
|
System.arraycopy(data, start, forDigest, 0, sig - start);
|
||||||
descriptorDigestSha256Base64 = Base64.encodeBase64String(
|
descriptorDigestSha256Base64 = Base64.encodeBase64String(
|
||||||
DigestUtils.sha256(DigestUtils.sha256(forDigest))).
|
DigestUtils.sha256(DigestUtils.sha256(forDigest)))
|
||||||
replaceAll("=", "");
|
.replaceAll("=", "");
|
||||||
}
|
}
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
/* Handle below. */
|
/* Handle below. */
|
||||||
@ -1010,14 +1018,16 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
public void sanitizeAndStoreExtraInfoDescriptor(byte[] data) {
|
public void sanitizeAndStoreExtraInfoDescriptor(byte[] data) {
|
||||||
|
|
||||||
/* Parse descriptor to generate a sanitized version. */
|
/* Parse descriptor to generate a sanitized version. */
|
||||||
String scrubbedDesc = null, published = null,
|
String scrubbedDesc = null;
|
||||||
masterKeyEd25519FromIdentityEd25519 = null;
|
String published = null;
|
||||||
|
String masterKeyEd25519FromIdentityEd25519 = null;
|
||||||
try {
|
try {
|
||||||
BufferedReader br = new BufferedReader(new StringReader(new String(
|
BufferedReader br = new BufferedReader(new StringReader(new String(
|
||||||
data, "US-ASCII")));
|
data, "US-ASCII")));
|
||||||
String line = null;
|
String line = null;
|
||||||
StringBuilder scrubbed = null;
|
StringBuilder scrubbed = null;
|
||||||
String hashedBridgeIdentity = null, masterKeyEd25519 = null;
|
String hashedBridgeIdentity = null;
|
||||||
|
String masterKeyEd25519 = null;
|
||||||
while ((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
|
|
||||||
/* Parse bridge identity from extra-info line and replace it with
|
/* Parse bridge identity from extra-info line and replace it with
|
||||||
@ -1054,8 +1064,8 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
/* Extract master-key-ed25519 from identity-ed25519. */
|
/* Extract master-key-ed25519 from identity-ed25519. */
|
||||||
} else if (line.equals("identity-ed25519")) {
|
} else if (line.equals("identity-ed25519")) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
while ((line = br.readLine()) != null &&
|
while ((line = br.readLine()) != null
|
||||||
!line.equals("-----END ED25519 CERT-----")) {
|
&& !line.equals("-----END ED25519 CERT-----")) {
|
||||||
if (line.equals("-----BEGIN ED25519 CERT-----")) {
|
if (line.equals("-----BEGIN ED25519 CERT-----")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1066,8 +1076,8 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
sb.toString());
|
sb.toString());
|
||||||
String sha256MasterKeyEd25519 = Base64.encodeBase64String(
|
String sha256MasterKeyEd25519 = Base64.encodeBase64String(
|
||||||
DigestUtils.sha256(Base64.decodeBase64(
|
DigestUtils.sha256(Base64.decodeBase64(
|
||||||
masterKeyEd25519FromIdentityEd25519 + "="))).
|
masterKeyEd25519FromIdentityEd25519 + "=")))
|
||||||
replaceAll("=", "");
|
.replaceAll("=", "");
|
||||||
scrubbed.append("master-key-ed25519 " + sha256MasterKeyEd25519
|
scrubbed.append("master-key-ed25519 " + sha256MasterKeyEd25519
|
||||||
+ "\n");
|
+ "\n");
|
||||||
if (masterKeyEd25519 != null && !masterKeyEd25519.equals(
|
if (masterKeyEd25519 != null && !masterKeyEd25519.equals(
|
||||||
@ -1080,8 +1090,8 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
/* Verify that identity-ed25519 and master-key-ed25519 match. */
|
/* Verify that identity-ed25519 and master-key-ed25519 match. */
|
||||||
} else if (line.startsWith("master-key-ed25519 ")) {
|
} else if (line.startsWith("master-key-ed25519 ")) {
|
||||||
masterKeyEd25519 = line.substring(line.indexOf(" ") + 1);
|
masterKeyEd25519 = line.substring(line.indexOf(" ") + 1);
|
||||||
if (masterKeyEd25519FromIdentityEd25519 != null &&
|
if (masterKeyEd25519FromIdentityEd25519 != null
|
||||||
!masterKeyEd25519FromIdentityEd25519.equals(
|
&& !masterKeyEd25519FromIdentityEd25519.equals(
|
||||||
masterKeyEd25519)) {
|
masterKeyEd25519)) {
|
||||||
this.logger.warning("Mismatch between identity-ed25519 and "
|
this.logger.warning("Mismatch between identity-ed25519 and "
|
||||||
+ "master-key-ed25519. Skipping.");
|
+ "master-key-ed25519. Skipping.");
|
||||||
@ -1169,8 +1179,8 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
byte[] forDigest = new byte[sig - start];
|
byte[] forDigest = new byte[sig - start];
|
||||||
System.arraycopy(data, start, forDigest, 0, sig - start);
|
System.arraycopy(data, start, forDigest, 0, sig - start);
|
||||||
descriptorDigestSha256Base64 = Base64.encodeBase64String(
|
descriptorDigestSha256Base64 = Base64.encodeBase64String(
|
||||||
DigestUtils.sha256(DigestUtils.sha256(forDigest))).
|
DigestUtils.sha256(DigestUtils.sha256(forDigest)))
|
||||||
replaceAll("=", "");
|
.replaceAll("=", "");
|
||||||
}
|
}
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
/* Handle below. */
|
/* Handle below. */
|
||||||
@ -1230,11 +1240,12 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
public void finishWriting() {
|
public void finishWriting() {
|
||||||
|
|
||||||
/* Delete secrets that we don't need anymore. */
|
/* Delete secrets that we don't need anymore. */
|
||||||
if (!this.secretsForHashingIPAddresses.isEmpty() &&
|
if (!this.secretsForHashingIPAddresses.isEmpty()
|
||||||
this.secretsForHashingIPAddresses.firstKey().compareTo(
|
&& this.secretsForHashingIPAddresses.firstKey().compareTo(
|
||||||
this.bridgeSanitizingCutOffTimestamp) < 0) {
|
this.bridgeSanitizingCutOffTimestamp) < 0) {
|
||||||
try {
|
try {
|
||||||
int kept = 0, deleted = 0;
|
int kept = 0;
|
||||||
|
int deleted = 0;
|
||||||
BufferedWriter bw = new BufferedWriter(new FileWriter(
|
BufferedWriter bw = new BufferedWriter(new FileWriter(
|
||||||
this.bridgeIpSecretsFile));
|
this.bridgeIpSecretsFile));
|
||||||
for (Map.Entry<String, byte[]> e :
|
for (Map.Entry<String, byte[]> e :
|
||||||
@ -1267,26 +1278,26 @@ public class SanitizedBridgesWriter extends Thread {
|
|||||||
try {
|
try {
|
||||||
long maxNetworkStatusPublishedMillis =
|
long maxNetworkStatusPublishedMillis =
|
||||||
dateTimeFormat.parse(maxNetworkStatusPublishedTime).getTime();
|
dateTimeFormat.parse(maxNetworkStatusPublishedTime).getTime();
|
||||||
if (maxNetworkStatusPublishedMillis > 0L &&
|
if (maxNetworkStatusPublishedMillis > 0L
|
||||||
maxNetworkStatusPublishedMillis < tooOldMillis) {
|
&& maxNetworkStatusPublishedMillis < tooOldMillis) {
|
||||||
this.logger.warning("The last known bridge network status was "
|
this.logger.warning("The last known bridge network status was "
|
||||||
+ "published " + maxNetworkStatusPublishedTime + ", which is "
|
+ "published " + maxNetworkStatusPublishedTime + ", which is "
|
||||||
+ "more than 5:30 hours in the past.");
|
+ "more than 5:30 hours in the past.");
|
||||||
}
|
}
|
||||||
long maxServerDescriptorPublishedMillis =
|
long maxServerDescriptorPublishedMillis =
|
||||||
dateTimeFormat.parse(maxServerDescriptorPublishedTime).
|
dateTimeFormat.parse(maxServerDescriptorPublishedTime)
|
||||||
getTime();
|
.getTime();
|
||||||
if (maxServerDescriptorPublishedMillis > 0L &&
|
if (maxServerDescriptorPublishedMillis > 0L
|
||||||
maxServerDescriptorPublishedMillis < tooOldMillis) {
|
&& maxServerDescriptorPublishedMillis < tooOldMillis) {
|
||||||
this.logger.warning("The last known bridge server descriptor was "
|
this.logger.warning("The last known bridge server descriptor was "
|
||||||
+ "published " + maxServerDescriptorPublishedTime + ", which "
|
+ "published " + maxServerDescriptorPublishedTime + ", which "
|
||||||
+ "is more than 5:30 hours in the past.");
|
+ "is more than 5:30 hours in the past.");
|
||||||
}
|
}
|
||||||
long maxExtraInfoDescriptorPublishedMillis =
|
long maxExtraInfoDescriptorPublishedMillis =
|
||||||
dateTimeFormat.parse(maxExtraInfoDescriptorPublishedTime).
|
dateTimeFormat.parse(maxExtraInfoDescriptorPublishedTime)
|
||||||
getTime();
|
.getTime();
|
||||||
if (maxExtraInfoDescriptorPublishedMillis > 0L &&
|
if (maxExtraInfoDescriptorPublishedMillis > 0L
|
||||||
maxExtraInfoDescriptorPublishedMillis < tooOldMillis) {
|
&& maxExtraInfoDescriptorPublishedMillis < tooOldMillis) {
|
||||||
this.logger.warning("The last known bridge extra-info descriptor "
|
this.logger.warning("The last known bridge extra-info descriptor "
|
||||||
+ "was published " + maxExtraInfoDescriptorPublishedTime
|
+ "was published " + maxExtraInfoDescriptorPublishedTime
|
||||||
+ ", which is more than 5:30 hours in the past.");
|
+ ", which is more than 5:30 hours in the past.");
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
/* Copyright 2011--2016 The Tor Project
|
/* Copyright 2011--2016 The Tor Project
|
||||||
* See LICENSE for licensing information */
|
* See LICENSE for licensing information */
|
||||||
|
|
||||||
package org.torproject.collector.bridgepools;
|
package org.torproject.collector.bridgepools;
|
||||||
|
|
||||||
|
import org.torproject.collector.main.Configuration;
|
||||||
|
import org.torproject.collector.main.LockFile;
|
||||||
|
import org.torproject.collector.main.LoggingConfiguration;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.DecoderException;
|
||||||
|
import org.apache.commons.codec.binary.Hex;
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -24,14 +34,6 @@ import java.util.TreeSet;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.apache.commons.codec.DecoderException;
|
|
||||||
import org.apache.commons.codec.binary.Hex;
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
|
||||||
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
|
|
||||||
import org.torproject.collector.main.Configuration;
|
|
||||||
import org.torproject.collector.main.LockFile;
|
|
||||||
import org.torproject.collector.main.LoggingConfiguration;
|
|
||||||
|
|
||||||
public class BridgePoolAssignmentsProcessor extends Thread {
|
public class BridgePoolAssignmentsProcessor extends Thread {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
@ -77,8 +79,8 @@ public class BridgePoolAssignmentsProcessor extends Thread {
|
|||||||
|
|
||||||
Logger logger =
|
Logger logger =
|
||||||
Logger.getLogger(BridgePoolAssignmentsProcessor.class.getName());
|
Logger.getLogger(BridgePoolAssignmentsProcessor.class.getName());
|
||||||
if (assignmentsDirectory == null ||
|
if (assignmentsDirectory == null
|
||||||
sanitizedAssignmentsDirectory == null) {
|
|| sanitizedAssignmentsDirectory == null) {
|
||||||
IllegalArgumentException e = new IllegalArgumentException("Neither "
|
IllegalArgumentException e = new IllegalArgumentException("Neither "
|
||||||
+ "assignmentsDirectory nor sanitizedAssignmentsDirectory may "
|
+ "assignmentsDirectory nor sanitizedAssignmentsDirectory may "
|
||||||
+ "be null!");
|
+ "be null!");
|
||||||
@ -117,9 +119,11 @@ public class BridgePoolAssignmentsProcessor extends Thread {
|
|||||||
} else {
|
} else {
|
||||||
br = new BufferedReader(new FileReader(assignmentFile));
|
br = new BufferedReader(new FileReader(assignmentFile));
|
||||||
}
|
}
|
||||||
String line, bridgePoolAssignmentLine = null;
|
String line;
|
||||||
|
String bridgePoolAssignmentLine = null;
|
||||||
SortedSet<String> sanitizedAssignments = new TreeSet<String>();
|
SortedSet<String> sanitizedAssignments = new TreeSet<String>();
|
||||||
boolean wroteLastLine = false, skipBefore20120504125947 = true;
|
boolean wroteLastLine = false;
|
||||||
|
boolean skipBefore20120504125947 = true;
|
||||||
Set<String> hashedFingerprints = null;
|
Set<String> hashedFingerprints = null;
|
||||||
while ((line = br.readLine()) != null || !wroteLastLine) {
|
while ((line = br.readLine()) != null || !wroteLastLine) {
|
||||||
if (line != null && line.startsWith("bridge-pool-assignment ")) {
|
if (line != null && line.startsWith("bridge-pool-assignment ")) {
|
||||||
@ -142,8 +146,8 @@ public class BridgePoolAssignmentsProcessor extends Thread {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (line == null ||
|
if (line == null
|
||||||
line.startsWith("bridge-pool-assignment ")) {
|
|| line.startsWith("bridge-pool-assignment ")) {
|
||||||
if (bridgePoolAssignmentLine != null) {
|
if (bridgePoolAssignmentLine != null) {
|
||||||
try {
|
try {
|
||||||
long bridgePoolAssignmentTime = assignmentFormat.parse(
|
long bridgePoolAssignmentTime = assignmentFormat.parse(
|
||||||
@ -235,8 +239,8 @@ public class BridgePoolAssignmentsProcessor extends Thread {
|
|||||||
+ "starting with '" + duplicateFingerprint + "'.");
|
+ "starting with '" + duplicateFingerprint + "'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxBridgePoolAssignmentTime > 0L &&
|
if (maxBridgePoolAssignmentTime > 0L
|
||||||
maxBridgePoolAssignmentTime + 330L * 60L * 1000L
|
&& maxBridgePoolAssignmentTime + 330L * 60L * 1000L
|
||||||
< System.currentTimeMillis()) {
|
< System.currentTimeMillis()) {
|
||||||
SimpleDateFormat dateTimeFormat = new SimpleDateFormat(
|
SimpleDateFormat dateTimeFormat = new SimpleDateFormat(
|
||||||
"yyyy-MM-dd HH:mm:ss");
|
"yyyy-MM-dd HH:mm:ss");
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
/* Copyright 2010--2016 The Tor Project
|
/* Copyright 2010--2016 The Tor Project
|
||||||
* See LICENSE for licensing information */
|
* See LICENSE for licensing information */
|
||||||
|
|
||||||
package org.torproject.collector.exitlists;
|
package org.torproject.collector.exitlists;
|
||||||
|
|
||||||
|
import org.torproject.collector.main.Configuration;
|
||||||
|
import org.torproject.collector.main.LockFile;
|
||||||
|
import org.torproject.collector.main.LoggingConfiguration;
|
||||||
|
import org.torproject.descriptor.Descriptor;
|
||||||
|
import org.torproject.descriptor.DescriptorParseException;
|
||||||
|
import org.torproject.descriptor.DescriptorParser;
|
||||||
|
import org.torproject.descriptor.DescriptorSourceFactory;
|
||||||
|
import org.torproject.descriptor.ExitList;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -20,15 +30,6 @@ import java.util.TreeSet;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.torproject.descriptor.Descriptor;
|
|
||||||
import org.torproject.descriptor.DescriptorParser;
|
|
||||||
import org.torproject.descriptor.DescriptorSourceFactory;
|
|
||||||
import org.torproject.descriptor.ExitList;
|
|
||||||
import org.torproject.descriptor.DescriptorParseException;
|
|
||||||
import org.torproject.collector.main.Configuration;
|
|
||||||
import org.torproject.collector.main.LockFile;
|
|
||||||
import org.torproject.collector.main.LoggingConfiguration;
|
|
||||||
|
|
||||||
public class ExitListDownloader extends Thread {
|
public class ExitListDownloader extends Thread {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
@ -85,8 +86,8 @@ public class ExitListDownloader extends Thread {
|
|||||||
huc.connect();
|
huc.connect();
|
||||||
int response = huc.getResponseCode();
|
int response = huc.getResponseCode();
|
||||||
if (response != 200) {
|
if (response != 200) {
|
||||||
logger.warning("Could not download exit list. Response code " +
|
logger.warning("Could not download exit list. Response code "
|
||||||
response);
|
+ response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BufferedInputStream in = new BufferedInputStream(
|
BufferedInputStream in = new BufferedInputStream(
|
||||||
@ -121,8 +122,8 @@ public class ExitListDownloader extends Thread {
|
|||||||
List<Descriptor> parsedDescriptors =
|
List<Descriptor> parsedDescriptors =
|
||||||
descriptorParser.parseDescriptors(downloadedExitList.getBytes(),
|
descriptorParser.parseDescriptors(downloadedExitList.getBytes(),
|
||||||
tarballFile.getName());
|
tarballFile.getName());
|
||||||
if (parsedDescriptors.size() != 1 ||
|
if (parsedDescriptors.size() != 1
|
||||||
!(parsedDescriptors.get(0) instanceof ExitList)) {
|
|| !(parsedDescriptors.get(0) instanceof ExitList)) {
|
||||||
logger.warning("Could not parse downloaded exit list");
|
logger.warning("Could not parse downloaded exit list");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -136,12 +137,12 @@ public class ExitListDownloader extends Thread {
|
|||||||
logger.log(Level.WARNING, "Could not parse downloaded exit list",
|
logger.log(Level.WARNING, "Could not parse downloaded exit list",
|
||||||
e);
|
e);
|
||||||
}
|
}
|
||||||
if (maxScanMillis > 0L &&
|
if (maxScanMillis > 0L
|
||||||
maxScanMillis + 330L * 60L * 1000L < System.currentTimeMillis()) {
|
&& maxScanMillis + 330L * 60L * 1000L < System.currentTimeMillis()) {
|
||||||
logger.warning("The last reported scan in the downloaded exit list "
|
logger.warning("The last reported scan in the downloaded exit list "
|
||||||
+ "took place at " + dateTimeFormat.format(maxScanMillis)
|
+ "took place at " + dateTimeFormat.format(maxScanMillis)
|
||||||
+ ", which is more than 5:30 hours in the past.");
|
+ ", which is more than 5:30 hours in the past.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write to disk. */
|
/* Write to disk. */
|
||||||
File rsyncFile = new File("recent/exit-lists/"
|
File rsyncFile = new File("recent/exit-lists/"
|
||||||
|
@ -1,7 +1,14 @@
|
|||||||
/* Copyright 2015 The Tor Project
|
/* Copyright 2015--2016 The Tor Project
|
||||||
* See LICENSE for licensing information */
|
* See LICENSE for licensing information */
|
||||||
|
|
||||||
package org.torproject.collector.index;
|
package org.torproject.collector.index;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
|
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;
|
||||||
|
import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@ -17,12 +24,6 @@ import java.util.TimeZone;
|
|||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.zip.GZIPOutputStream;
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;
|
|
||||||
import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
|
|
||||||
/* Create a fresh index.json containing all directories and files in the
|
/* Create a fresh index.json containing all directories and files in the
|
||||||
* archive/ and recent/ directories.
|
* archive/ and recent/ directories.
|
||||||
*
|
*
|
||||||
@ -53,12 +54,14 @@ public class CreateIndexJson {
|
|||||||
String path;
|
String path;
|
||||||
SortedSet<FileNode> files;
|
SortedSet<FileNode> files;
|
||||||
SortedSet<DirectoryNode> directories;
|
SortedSet<DirectoryNode> directories;
|
||||||
|
|
||||||
DirectoryNode(String path, SortedSet<FileNode> files,
|
DirectoryNode(String path, SortedSet<FileNode> files,
|
||||||
SortedSet<DirectoryNode> directories) {
|
SortedSet<DirectoryNode> directories) {
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.files = files;
|
this.files = files;
|
||||||
this.directories = directories;
|
this.directories = directories;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compareTo(DirectoryNode o) {
|
public int compareTo(DirectoryNode o) {
|
||||||
return this.path.compareTo(o.path);
|
return this.path.compareTo(o.path);
|
||||||
}
|
}
|
||||||
@ -69,6 +72,7 @@ public class CreateIndexJson {
|
|||||||
String path;
|
String path;
|
||||||
SortedSet<FileNode> files;
|
SortedSet<FileNode> files;
|
||||||
SortedSet<DirectoryNode> directories;
|
SortedSet<DirectoryNode> directories;
|
||||||
|
|
||||||
IndexNode(String index_created, String path,
|
IndexNode(String index_created, String path,
|
||||||
SortedSet<FileNode> files,
|
SortedSet<FileNode> files,
|
||||||
SortedSet<DirectoryNode> directories) {
|
SortedSet<DirectoryNode> directories) {
|
||||||
@ -83,17 +87,20 @@ public class CreateIndexJson {
|
|||||||
String path;
|
String path;
|
||||||
long size;
|
long size;
|
||||||
String last_modified;
|
String last_modified;
|
||||||
|
|
||||||
FileNode(String path, long size, String last_modified) {
|
FileNode(String path, long size, String last_modified) {
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.last_modified = last_modified;
|
this.last_modified = last_modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compareTo(FileNode o) {
|
public int compareTo(FileNode o) {
|
||||||
return this.path.compareTo(o.path);
|
return this.path.compareTo(o.path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static DateFormat dateTimeFormat;
|
static DateFormat dateTimeFormat;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
dateTimeFormat = new SimpleDateFormat(dateTimePattern,
|
dateTimeFormat = new SimpleDateFormat(dateTimePattern,
|
||||||
dateTimeLocale);
|
dateTimeLocale);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* Copyright 2010--2012 The Tor Project
|
/* Copyright 2010--2016 The Tor Project
|
||||||
* See LICENSE for licensing information */
|
* See LICENSE for licensing information */
|
||||||
|
|
||||||
package org.torproject.collector.main;
|
package org.torproject.collector.main;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
@ -67,6 +68,7 @@ public class Configuration {
|
|||||||
private String torperfOutputDirectory = "out/torperf/";
|
private String torperfOutputDirectory = "out/torperf/";
|
||||||
private SortedMap<String, String> torperfSources = null;
|
private SortedMap<String, String> torperfSources = null;
|
||||||
private List<String> torperfFiles = null;
|
private List<String> torperfFiles = null;
|
||||||
|
|
||||||
public Configuration() {
|
public Configuration() {
|
||||||
|
|
||||||
/* Initialize logger. */
|
/* Initialize logger. */
|
||||||
@ -219,84 +221,111 @@ public class Configuration {
|
|||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDirectoryArchivesOutputDirectory() {
|
public String getDirectoryArchivesOutputDirectory() {
|
||||||
return this.directoryArchivesOutputDirectory;
|
return this.directoryArchivesOutputDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getImportCachedRelayDescriptors() {
|
public boolean getImportCachedRelayDescriptors() {
|
||||||
return this.importCachedRelayDescriptors;
|
return this.importCachedRelayDescriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getCachedRelayDescriptorDirectory() {
|
public List<String> getCachedRelayDescriptorDirectory() {
|
||||||
return this.cachedRelayDescriptorsDirectory;
|
return this.cachedRelayDescriptorsDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getImportDirectoryArchives() {
|
public boolean getImportDirectoryArchives() {
|
||||||
return this.importDirectoryArchives;
|
return this.importDirectoryArchives;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDirectoryArchivesDirectory() {
|
public String getDirectoryArchivesDirectory() {
|
||||||
return this.directoryArchivesDirectory;
|
return this.directoryArchivesDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getKeepDirectoryArchiveImportHistory() {
|
public boolean getKeepDirectoryArchiveImportHistory() {
|
||||||
return this.keepDirectoryArchiveImportHistory;
|
return this.keepDirectoryArchiveImportHistory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getReplaceIPAddressesWithHashes() {
|
public boolean getReplaceIPAddressesWithHashes() {
|
||||||
return this.replaceIPAddressesWithHashes;
|
return this.replaceIPAddressesWithHashes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLimitBridgeDescriptorMappings() {
|
public long getLimitBridgeDescriptorMappings() {
|
||||||
return this.limitBridgeDescriptorMappings;
|
return this.limitBridgeDescriptorMappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSanitizedBridgesWriteDirectory() {
|
public String getSanitizedBridgesWriteDirectory() {
|
||||||
return this.sanitizedBridgesWriteDirectory;
|
return this.sanitizedBridgesWriteDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBridgeSnapshotsDirectory() {
|
public String getBridgeSnapshotsDirectory() {
|
||||||
return this.bridgeSnapshotsDirectory;
|
return this.bridgeSnapshotsDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getDownloadRelayDescriptors() {
|
public boolean getDownloadRelayDescriptors() {
|
||||||
return this.downloadRelayDescriptors;
|
return this.downloadRelayDescriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getDownloadFromDirectoryAuthorities() {
|
public List<String> getDownloadFromDirectoryAuthorities() {
|
||||||
return this.downloadFromDirectoryAuthorities;
|
return this.downloadFromDirectoryAuthorities;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getDownloadVotesByFingerprint() {
|
public List<String> getDownloadVotesByFingerprint() {
|
||||||
return this.downloadVotesByFingerprint;
|
return this.downloadVotesByFingerprint;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getDownloadCurrentConsensus() {
|
public boolean getDownloadCurrentConsensus() {
|
||||||
return this.downloadCurrentConsensus;
|
return this.downloadCurrentConsensus;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getDownloadCurrentMicrodescConsensus() {
|
public boolean getDownloadCurrentMicrodescConsensus() {
|
||||||
return this.downloadCurrentMicrodescConsensus;
|
return this.downloadCurrentMicrodescConsensus;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getDownloadCurrentVotes() {
|
public boolean getDownloadCurrentVotes() {
|
||||||
return this.downloadCurrentVotes;
|
return this.downloadCurrentVotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getDownloadMissingServerDescriptors() {
|
public boolean getDownloadMissingServerDescriptors() {
|
||||||
return this.downloadMissingServerDescriptors;
|
return this.downloadMissingServerDescriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getDownloadMissingExtraInfoDescriptors() {
|
public boolean getDownloadMissingExtraInfoDescriptors() {
|
||||||
return this.downloadMissingExtraInfoDescriptors;
|
return this.downloadMissingExtraInfoDescriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getDownloadMissingMicrodescriptors() {
|
public boolean getDownloadMissingMicrodescriptors() {
|
||||||
return this.downloadMissingMicrodescriptors;
|
return this.downloadMissingMicrodescriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getDownloadAllServerDescriptors() {
|
public boolean getDownloadAllServerDescriptors() {
|
||||||
return this.downloadAllServerDescriptors;
|
return this.downloadAllServerDescriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getDownloadAllExtraInfoDescriptors() {
|
public boolean getDownloadAllExtraInfoDescriptors() {
|
||||||
return this.downloadAllExtraInfoDescriptors;
|
return this.downloadAllExtraInfoDescriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getCompressRelayDescriptorDownloads() {
|
public boolean getCompressRelayDescriptorDownloads() {
|
||||||
return this.compressRelayDescriptorDownloads;
|
return this.compressRelayDescriptorDownloads;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAssignmentsDirectory() {
|
public String getAssignmentsDirectory() {
|
||||||
return this.assignmentsDirectory;
|
return this.assignmentsDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSanitizedAssignmentsDirectory() {
|
public String getSanitizedAssignmentsDirectory() {
|
||||||
return this.sanitizedAssignmentsDirectory;
|
return this.sanitizedAssignmentsDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTorperfOutputDirectory() {
|
public String getTorperfOutputDirectory() {
|
||||||
return this.torperfOutputDirectory;
|
return this.torperfOutputDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SortedMap<String, String> getTorperfSources() {
|
public SortedMap<String, String> getTorperfSources() {
|
||||||
return this.torperfSources;
|
return this.torperfSources;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getTorperfFiles() {
|
public List<String> getTorperfFiles() {
|
||||||
return this.torperfFiles;
|
return this.torperfFiles;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* Copyright 2010--2012 The Tor Project
|
/* Copyright 2010--2016 The Tor Project
|
||||||
* See LICENSE for licensing information */
|
* See LICENSE for licensing information */
|
||||||
|
|
||||||
package org.torproject.collector.main;
|
package org.torproject.collector.main;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* Copyright 2010--2016 The Tor Project
|
/* Copyright 2010--2016 The Tor Project
|
||||||
* See LICENSE for licensing information */
|
* See LICENSE for licensing information */
|
||||||
|
|
||||||
package org.torproject.collector.main;
|
package org.torproject.collector.main;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
/* Copyright 2010--2014 The Tor Project
|
/* Copyright 2010--2016 The Tor Project
|
||||||
* See LICENSE for licensing information */
|
* See LICENSE for licensing information */
|
||||||
|
|
||||||
package org.torproject.collector.relaydescs;
|
package org.torproject.collector.relaydescs;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
@ -28,10 +33,6 @@ import java.util.TreeSet;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
|
||||||
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read in all files in a given directory and pass buffered readers of
|
* Read in all files in a given directory and pass buffered readers of
|
||||||
* them to the relay descriptor parser.
|
* them to the relay descriptor parser.
|
||||||
@ -40,13 +41,14 @@ public class ArchiveReader {
|
|||||||
public ArchiveReader(RelayDescriptorParser rdp, File archivesDirectory,
|
public ArchiveReader(RelayDescriptorParser rdp, File archivesDirectory,
|
||||||
File statsDirectory, boolean keepImportHistory) {
|
File statsDirectory, boolean keepImportHistory) {
|
||||||
|
|
||||||
if (rdp == null || archivesDirectory == null ||
|
if (rdp == null || archivesDirectory == null
|
||||||
statsDirectory == null) {
|
|| statsDirectory == null) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
rdp.setArchiveReader(this);
|
rdp.setArchiveReader(this);
|
||||||
int parsedFiles = 0, ignoredFiles = 0;
|
int parsedFiles = 0;
|
||||||
|
int ignoredFiles = 0;
|
||||||
Logger logger = Logger.getLogger(ArchiveReader.class.getName());
|
Logger logger = Logger.getLogger(ArchiveReader.class.getName());
|
||||||
SortedSet<String> archivesImportHistory = new TreeSet<String>();
|
SortedSet<String> archivesImportHistory = new TreeSet<String>();
|
||||||
File archivesImportHistoryFile = new File(statsDirectory,
|
File archivesImportHistoryFile = new File(statsDirectory,
|
||||||
@ -82,8 +84,8 @@ public class ArchiveReader {
|
|||||||
if (rdp != null) {
|
if (rdp != null) {
|
||||||
try {
|
try {
|
||||||
BufferedInputStream bis = null;
|
BufferedInputStream bis = null;
|
||||||
if (keepImportHistory &&
|
if (keepImportHistory
|
||||||
archivesImportHistory.contains(pop.getName())) {
|
&& archivesImportHistory.contains(pop.getName())) {
|
||||||
ignoredFiles++;
|
ignoredFiles++;
|
||||||
continue;
|
continue;
|
||||||
} else if (pop.getName().endsWith(".tar.bz2")) {
|
} else if (pop.getName().endsWith(".tar.bz2")) {
|
||||||
@ -176,7 +178,8 @@ public class ArchiveReader {
|
|||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
/* No way that US-ASCII is not supported. */
|
/* No way that US-ASCII is not supported. */
|
||||||
}
|
}
|
||||||
int start = -1, end = -1;
|
int start = -1;
|
||||||
|
int end = -1;
|
||||||
String startToken = "onion-key\n";
|
String startToken = "onion-key\n";
|
||||||
while (end < ascii.length()) {
|
while (end < ascii.length()) {
|
||||||
start = ascii.indexOf(startToken, end);
|
start = ascii.indexOf(startToken, end);
|
||||||
@ -198,8 +201,8 @@ public class ArchiveReader {
|
|||||||
if (!this.microdescriptorValidAfterTimes.containsKey(
|
if (!this.microdescriptorValidAfterTimes.containsKey(
|
||||||
digest256Hex)) {
|
digest256Hex)) {
|
||||||
logger.fine("Could not store microdescriptor '"
|
logger.fine("Could not store microdescriptor '"
|
||||||
+ digest256Hex + "', which was not contained in a "
|
+ digest256Hex + "', which was not contained in a "
|
||||||
+ "microdesc consensus.");
|
+ "microdesc consensus.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (String validAfterTime :
|
for (String validAfterTime :
|
||||||
@ -265,6 +268,7 @@ public class ArchiveReader {
|
|||||||
|
|
||||||
private Map<String, Set<String>> microdescriptorValidAfterTimes =
|
private Map<String, Set<String>> microdescriptorValidAfterTimes =
|
||||||
new HashMap<String, Set<String>>();
|
new HashMap<String, Set<String>>();
|
||||||
|
|
||||||
public void haveParsedMicrodescConsensus(String validAfterTime,
|
public void haveParsedMicrodescConsensus(String validAfterTime,
|
||||||
SortedSet<String> microdescriptorDigests) {
|
SortedSet<String> microdescriptorDigests) {
|
||||||
for (String microdescriptor : microdescriptorDigests) {
|
for (String microdescriptor : microdescriptorDigests) {
|
||||||
|
@ -1,7 +1,15 @@
|
|||||||
/* Copyright 2010--2016 The Tor Project
|
/* Copyright 2010--2016 The Tor Project
|
||||||
* See LICENSE for licensing information */
|
* See LICENSE for licensing information */
|
||||||
|
|
||||||
package org.torproject.collector.relaydescs;
|
package org.torproject.collector.relaydescs;
|
||||||
|
|
||||||
|
import org.torproject.collector.main.Configuration;
|
||||||
|
import org.torproject.collector.main.LockFile;
|
||||||
|
import org.torproject.collector.main.LoggingConfiguration;
|
||||||
|
import org.torproject.descriptor.DescriptorParseException;
|
||||||
|
import org.torproject.descriptor.DescriptorParser;
|
||||||
|
import org.torproject.descriptor.DescriptorSourceFactory;
|
||||||
|
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
@ -27,13 +35,6 @@ import java.util.TreeMap;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.torproject.descriptor.DescriptorParser;
|
|
||||||
import org.torproject.descriptor.DescriptorSourceFactory;
|
|
||||||
import org.torproject.descriptor.DescriptorParseException;
|
|
||||||
import org.torproject.collector.main.Configuration;
|
|
||||||
import org.torproject.collector.main.LockFile;
|
|
||||||
import org.torproject.collector.main.LoggingConfiguration;
|
|
||||||
|
|
||||||
public class ArchiveWriter extends Thread {
|
public class ArchiveWriter extends Thread {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
@ -78,11 +79,13 @@ public class ArchiveWriter extends Thread {
|
|||||||
private File outputDirectory;
|
private File outputDirectory;
|
||||||
private String rsyncCatString;
|
private String rsyncCatString;
|
||||||
private DescriptorParser descriptorParser;
|
private DescriptorParser descriptorParser;
|
||||||
private int storedConsensusesCounter = 0,
|
private int storedConsensusesCounter = 0;
|
||||||
storedMicrodescConsensusesCounter = 0, storedVotesCounter = 0,
|
private int storedMicrodescConsensusesCounter = 0;
|
||||||
storedCertsCounter = 0, storedServerDescriptorsCounter = 0,
|
private int storedVotesCounter = 0;
|
||||||
storedExtraInfoDescriptorsCounter = 0,
|
private int storedCertsCounter = 0;
|
||||||
storedMicrodescriptorsCounter = 0;
|
private int storedServerDescriptorsCounter = 0;
|
||||||
|
private int storedExtraInfoDescriptorsCounter = 0;
|
||||||
|
private int storedMicrodescriptorsCounter = 0;
|
||||||
|
|
||||||
private SortedMap<Long, SortedSet<String>> storedConsensuses =
|
private SortedMap<Long, SortedSet<String>> storedConsensuses =
|
||||||
new TreeMap<Long, SortedSet<String>>();
|
new TreeMap<Long, SortedSet<String>>();
|
||||||
@ -361,6 +364,7 @@ public class ArchiveWriter extends Thread {
|
|||||||
|
|
||||||
private static final byte[] CONSENSUS_ANNOTATION =
|
private static final byte[] CONSENSUS_ANNOTATION =
|
||||||
"@type network-status-consensus-3 1.0\n".getBytes();
|
"@type network-status-consensus-3 1.0\n".getBytes();
|
||||||
|
|
||||||
public void storeConsensus(byte[] data, long validAfter,
|
public void storeConsensus(byte[] data, long validAfter,
|
||||||
SortedSet<String> dirSources,
|
SortedSet<String> dirSources,
|
||||||
SortedSet<String> serverDescriptorDigests) {
|
SortedSet<String> serverDescriptorDigests) {
|
||||||
@ -376,8 +380,8 @@ public class ArchiveWriter extends Thread {
|
|||||||
if (this.store(CONSENSUS_ANNOTATION, data, outputFiles, null)) {
|
if (this.store(CONSENSUS_ANNOTATION, data, outputFiles, null)) {
|
||||||
this.storedConsensusesCounter++;
|
this.storedConsensusesCounter++;
|
||||||
}
|
}
|
||||||
if (!tarballFileExistedBefore &&
|
if (!tarballFileExistedBefore
|
||||||
this.now - validAfter < 3L * 60L * 60L * 1000L) {
|
&& this.now - validAfter < 3L * 60L * 60L * 1000L) {
|
||||||
this.storedConsensuses.put(validAfter, serverDescriptorDigests);
|
this.storedConsensuses.put(validAfter, serverDescriptorDigests);
|
||||||
this.expectedVotes.put(validAfter, dirSources.size());
|
this.expectedVotes.put(validAfter, dirSources.size());
|
||||||
}
|
}
|
||||||
@ -385,6 +389,7 @@ public class ArchiveWriter extends Thread {
|
|||||||
|
|
||||||
private static final byte[] MICRODESCCONSENSUS_ANNOTATION =
|
private static final byte[] MICRODESCCONSENSUS_ANNOTATION =
|
||||||
"@type network-status-microdesc-consensus-3 1.0\n".getBytes();
|
"@type network-status-microdesc-consensus-3 1.0\n".getBytes();
|
||||||
|
|
||||||
public void storeMicrodescConsensus(byte[] data, long validAfter,
|
public void storeMicrodescConsensus(byte[] data, long validAfter,
|
||||||
SortedSet<String> microdescriptorDigests) {
|
SortedSet<String> microdescriptorDigests) {
|
||||||
SimpleDateFormat yearMonthDirectoryFormat = new SimpleDateFormat(
|
SimpleDateFormat yearMonthDirectoryFormat = new SimpleDateFormat(
|
||||||
@ -406,8 +411,8 @@ public class ArchiveWriter extends Thread {
|
|||||||
null)) {
|
null)) {
|
||||||
this.storedMicrodescConsensusesCounter++;
|
this.storedMicrodescConsensusesCounter++;
|
||||||
}
|
}
|
||||||
if (!tarballFileExistedBefore &&
|
if (!tarballFileExistedBefore
|
||||||
this.now - validAfter < 3L * 60L * 60L * 1000L) {
|
&& this.now - validAfter < 3L * 60L * 60L * 1000L) {
|
||||||
this.storedMicrodescConsensuses.put(validAfter,
|
this.storedMicrodescConsensuses.put(validAfter,
|
||||||
microdescriptorDigests);
|
microdescriptorDigests);
|
||||||
}
|
}
|
||||||
@ -415,6 +420,7 @@ public class ArchiveWriter extends Thread {
|
|||||||
|
|
||||||
private static final byte[] VOTE_ANNOTATION =
|
private static final byte[] VOTE_ANNOTATION =
|
||||||
"@type network-status-vote-3 1.0\n".getBytes();
|
"@type network-status-vote-3 1.0\n".getBytes();
|
||||||
|
|
||||||
public void storeVote(byte[] data, long validAfter,
|
public void storeVote(byte[] data, long validAfter,
|
||||||
String fingerprint, String digest,
|
String fingerprint, String digest,
|
||||||
SortedSet<String> serverDescriptorDigests) {
|
SortedSet<String> serverDescriptorDigests) {
|
||||||
@ -431,8 +437,8 @@ public class ArchiveWriter extends Thread {
|
|||||||
if (this.store(VOTE_ANNOTATION, data, outputFiles, null)) {
|
if (this.store(VOTE_ANNOTATION, data, outputFiles, null)) {
|
||||||
this.storedVotesCounter++;
|
this.storedVotesCounter++;
|
||||||
}
|
}
|
||||||
if (!tarballFileExistedBefore &&
|
if (!tarballFileExistedBefore
|
||||||
this.now - validAfter < 3L * 60L * 60L * 1000L) {
|
&& this.now - validAfter < 3L * 60L * 60L * 1000L) {
|
||||||
if (!this.storedVotes.containsKey(validAfter)) {
|
if (!this.storedVotes.containsKey(validAfter)) {
|
||||||
this.storedVotes.put(validAfter,
|
this.storedVotes.put(validAfter,
|
||||||
new TreeMap<String, SortedSet<String>>());
|
new TreeMap<String, SortedSet<String>>());
|
||||||
@ -444,6 +450,7 @@ public class ArchiveWriter extends Thread {
|
|||||||
|
|
||||||
private static final byte[] CERTIFICATE_ANNOTATION =
|
private static final byte[] CERTIFICATE_ANNOTATION =
|
||||||
"@type dir-key-certificate-3 1.0\n".getBytes();
|
"@type dir-key-certificate-3 1.0\n".getBytes();
|
||||||
|
|
||||||
public void storeCertificate(byte[] data, String fingerprint,
|
public void storeCertificate(byte[] data, String fingerprint,
|
||||||
long published) {
|
long published) {
|
||||||
SimpleDateFormat printFormat = new SimpleDateFormat(
|
SimpleDateFormat printFormat = new SimpleDateFormat(
|
||||||
@ -459,6 +466,7 @@ public class ArchiveWriter extends Thread {
|
|||||||
|
|
||||||
private static final byte[] SERVER_DESCRIPTOR_ANNOTATION =
|
private static final byte[] SERVER_DESCRIPTOR_ANNOTATION =
|
||||||
"@type server-descriptor 1.0\n".getBytes();
|
"@type server-descriptor 1.0\n".getBytes();
|
||||||
|
|
||||||
public void storeServerDescriptor(byte[] data, String digest,
|
public void storeServerDescriptor(byte[] data, String digest,
|
||||||
long published, String extraInfoDigest) {
|
long published, String extraInfoDigest) {
|
||||||
SimpleDateFormat printFormat = new SimpleDateFormat("yyyy/MM/");
|
SimpleDateFormat printFormat = new SimpleDateFormat("yyyy/MM/");
|
||||||
@ -477,8 +485,8 @@ public class ArchiveWriter extends Thread {
|
|||||||
append)) {
|
append)) {
|
||||||
this.storedServerDescriptorsCounter++;
|
this.storedServerDescriptorsCounter++;
|
||||||
}
|
}
|
||||||
if (!tarballFileExistedBefore &&
|
if (!tarballFileExistedBefore
|
||||||
this.now - published < 48L * 60L * 60L * 1000L) {
|
&& this.now - published < 48L * 60L * 60L * 1000L) {
|
||||||
if (!this.storedServerDescriptors.containsKey(published)) {
|
if (!this.storedServerDescriptors.containsKey(published)) {
|
||||||
this.storedServerDescriptors.put(published,
|
this.storedServerDescriptors.put(published,
|
||||||
new HashMap<String, String>());
|
new HashMap<String, String>());
|
||||||
@ -490,6 +498,7 @@ public class ArchiveWriter extends Thread {
|
|||||||
|
|
||||||
private static final byte[] EXTRA_INFO_ANNOTATION =
|
private static final byte[] EXTRA_INFO_ANNOTATION =
|
||||||
"@type extra-info 1.0\n".getBytes();
|
"@type extra-info 1.0\n".getBytes();
|
||||||
|
|
||||||
public void storeExtraInfoDescriptor(byte[] data,
|
public void storeExtraInfoDescriptor(byte[] data,
|
||||||
String extraInfoDigest, long published) {
|
String extraInfoDigest, long published) {
|
||||||
SimpleDateFormat descriptorFormat = new SimpleDateFormat("yyyy/MM/");
|
SimpleDateFormat descriptorFormat = new SimpleDateFormat("yyyy/MM/");
|
||||||
@ -507,8 +516,8 @@ public class ArchiveWriter extends Thread {
|
|||||||
if (this.store(EXTRA_INFO_ANNOTATION, data, outputFiles, append)) {
|
if (this.store(EXTRA_INFO_ANNOTATION, data, outputFiles, append)) {
|
||||||
this.storedExtraInfoDescriptorsCounter++;
|
this.storedExtraInfoDescriptorsCounter++;
|
||||||
}
|
}
|
||||||
if (!tarballFileExistedBefore &&
|
if (!tarballFileExistedBefore
|
||||||
this.now - published < 48L * 60L * 60L * 1000L) {
|
&& this.now - published < 48L * 60L * 60L * 1000L) {
|
||||||
if (!this.storedExtraInfoDescriptors.containsKey(published)) {
|
if (!this.storedExtraInfoDescriptors.containsKey(published)) {
|
||||||
this.storedExtraInfoDescriptors.put(published,
|
this.storedExtraInfoDescriptors.put(published,
|
||||||
new HashSet<String>());
|
new HashSet<String>());
|
||||||
@ -519,6 +528,7 @@ public class ArchiveWriter extends Thread {
|
|||||||
|
|
||||||
private static final byte[] MICRODESCRIPTOR_ANNOTATION =
|
private static final byte[] MICRODESCRIPTOR_ANNOTATION =
|
||||||
"@type microdescriptor 1.0\n".getBytes();
|
"@type microdescriptor 1.0\n".getBytes();
|
||||||
|
|
||||||
public void storeMicrodescriptor(byte[] data,
|
public void storeMicrodescriptor(byte[] data,
|
||||||
String microdescriptorDigest, long validAfter) {
|
String microdescriptorDigest, long validAfter) {
|
||||||
/* TODO We could check here whether we already stored the
|
/* TODO We could check here whether we already stored the
|
||||||
@ -545,8 +555,8 @@ public class ArchiveWriter extends Thread {
|
|||||||
append)) {
|
append)) {
|
||||||
this.storedMicrodescriptorsCounter++;
|
this.storedMicrodescriptorsCounter++;
|
||||||
}
|
}
|
||||||
if (!tarballFileExistedBefore &&
|
if (!tarballFileExistedBefore
|
||||||
this.now - validAfter < 40L * 24L * 60L * 60L * 1000L) {
|
&& this.now - validAfter < 40L * 24L * 60L * 60L * 1000L) {
|
||||||
if (!this.storedMicrodescriptors.containsKey(validAfter)) {
|
if (!this.storedMicrodescriptors.containsKey(validAfter)) {
|
||||||
this.storedMicrodescriptors.put(validAfter,
|
this.storedMicrodescriptors.put(validAfter,
|
||||||
new HashSet<String>());
|
new HashSet<String>());
|
||||||
@ -557,6 +567,7 @@ public class ArchiveWriter extends Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private StringBuilder intermediateStats = new StringBuilder();
|
private StringBuilder intermediateStats = new StringBuilder();
|
||||||
|
|
||||||
public void intermediateStats(String event) {
|
public void intermediateStats(String event) {
|
||||||
intermediateStats.append("While " + event + ", we stored "
|
intermediateStats.append("While " + event + ", we stored "
|
||||||
+ this.storedConsensusesCounter + " consensus(es), "
|
+ this.storedConsensusesCounter + " consensus(es), "
|
||||||
@ -600,8 +611,9 @@ public class ArchiveWriter extends Thread {
|
|||||||
for (Set<String> descriptors : this.storedMicrodescriptors.values()) {
|
for (Set<String> descriptors : this.storedMicrodescriptors.values()) {
|
||||||
knownMicrodescriptors.addAll(descriptors);
|
knownMicrodescriptors.addAll(descriptors);
|
||||||
}
|
}
|
||||||
boolean missingDescriptors = false, missingVotes = false,
|
boolean missingDescriptors = false;
|
||||||
missingMicrodescConsensus = false;
|
boolean missingVotes = false;
|
||||||
|
boolean missingMicrodescConsensus = false;
|
||||||
for (Map.Entry<Long, SortedSet<String>> c :
|
for (Map.Entry<Long, SortedSet<String>> c :
|
||||||
this.storedConsensuses.entrySet()) {
|
this.storedConsensuses.entrySet()) {
|
||||||
long validAfterMillis = c.getKey();
|
long validAfterMillis = c.getKey();
|
||||||
@ -613,8 +625,10 @@ public class ArchiveWriter extends Thread {
|
|||||||
foundVotes = this.storedVotes.get(validAfterMillis).size();
|
foundVotes = this.storedVotes.get(validAfterMillis).size();
|
||||||
for (Map.Entry<String, SortedSet<String>> v :
|
for (Map.Entry<String, SortedSet<String>> v :
|
||||||
this.storedVotes.get(validAfterMillis).entrySet()) {
|
this.storedVotes.get(validAfterMillis).entrySet()) {
|
||||||
int voteFoundServerDescs = 0, voteAllServerDescs = 0,
|
int voteFoundServerDescs = 0;
|
||||||
voteFoundExtraInfos = 0, voteAllExtraInfos = 0;
|
int voteAllServerDescs = 0;
|
||||||
|
int voteFoundExtraInfos = 0;
|
||||||
|
int voteAllExtraInfos = 0;
|
||||||
for (String serverDescriptorDigest : v.getValue()) {
|
for (String serverDescriptorDigest : v.getValue()) {
|
||||||
voteAllServerDescs++;
|
voteAllServerDescs++;
|
||||||
if (knownServerDescriptors.containsKey(
|
if (knownServerDescriptors.containsKey(
|
||||||
@ -636,32 +650,35 @@ public class ArchiveWriter extends Thread {
|
|||||||
if (voteAllServerDescs > 0) {
|
if (voteAllServerDescs > 0) {
|
||||||
sb.append(String.format(", %d/%d S (%.1f%%)",
|
sb.append(String.format(", %d/%d S (%.1f%%)",
|
||||||
voteFoundServerDescs, voteAllServerDescs,
|
voteFoundServerDescs, voteAllServerDescs,
|
||||||
100.0D * (double) voteFoundServerDescs /
|
100.0D * (double) voteFoundServerDescs
|
||||||
(double) voteAllServerDescs));
|
/ (double) voteAllServerDescs));
|
||||||
} else {
|
} else {
|
||||||
sb.append(", 0/0 S");
|
sb.append(", 0/0 S");
|
||||||
}
|
}
|
||||||
if (voteAllExtraInfos > 0) {
|
if (voteAllExtraInfos > 0) {
|
||||||
sb.append(String.format(", %d/%d E (%.1f%%)",
|
sb.append(String.format(", %d/%d E (%.1f%%)",
|
||||||
voteFoundExtraInfos, voteAllExtraInfos,
|
voteFoundExtraInfos, voteAllExtraInfos,
|
||||||
100.0D * (double) voteFoundExtraInfos /
|
100.0D * (double) voteFoundExtraInfos
|
||||||
(double) voteAllExtraInfos));
|
/ (double) voteAllExtraInfos));
|
||||||
} else {
|
} else {
|
||||||
sb.append(", 0/0 E");
|
sb.append(", 0/0 E");
|
||||||
}
|
}
|
||||||
String fingerprint = v.getKey();
|
String fingerprint = v.getKey();
|
||||||
/* Ignore turtles when warning about missing descriptors. */
|
/* Ignore turtles when warning about missing descriptors. */
|
||||||
if (!fingerprint.equalsIgnoreCase(
|
if (!fingerprint.equalsIgnoreCase(
|
||||||
"27B6B5996C426270A5C95488AA5BCEB6BCC86956") &&
|
"27B6B5996C426270A5C95488AA5BCEB6BCC86956")
|
||||||
(voteFoundServerDescs * 1000 < voteAllServerDescs * 995 ||
|
&& (voteFoundServerDescs * 1000 < voteAllServerDescs * 995
|
||||||
voteFoundExtraInfos * 1000 < voteAllExtraInfos * 995)) {
|
|| voteFoundExtraInfos * 1000 < voteAllExtraInfos * 995)) {
|
||||||
missingDescriptors = true;
|
missingDescriptors = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int foundServerDescs = 0, allServerDescs = 0, foundExtraInfos = 0,
|
int foundServerDescs = 0;
|
||||||
allExtraInfos = 0, foundMicrodescriptors = 0,
|
int allServerDescs = 0;
|
||||||
allMicrodescriptors = 0;
|
int foundExtraInfos = 0;
|
||||||
|
int allExtraInfos = 0;
|
||||||
|
int foundMicrodescriptors = 0;
|
||||||
|
int allMicrodescriptors = 0;
|
||||||
for (String serverDescriptorDigest : c.getValue()) {
|
for (String serverDescriptorDigest : c.getValue()) {
|
||||||
allServerDescs++;
|
allServerDescs++;
|
||||||
if (knownServerDescriptors.containsKey(
|
if (knownServerDescriptors.containsKey(
|
||||||
@ -688,15 +705,15 @@ public class ArchiveWriter extends Thread {
|
|||||||
}
|
}
|
||||||
if (allServerDescs > 0) {
|
if (allServerDescs > 0) {
|
||||||
sb.append(String.format(", %d/%d S (%.1f%%)", foundServerDescs,
|
sb.append(String.format(", %d/%d S (%.1f%%)", foundServerDescs,
|
||||||
allServerDescs, 100.0D * (double) foundServerDescs /
|
allServerDescs, 100.0D * (double) foundServerDescs
|
||||||
(double) allServerDescs));
|
/ (double) allServerDescs));
|
||||||
} else {
|
} else {
|
||||||
sb.append(", 0/0 S");
|
sb.append(", 0/0 S");
|
||||||
}
|
}
|
||||||
if (allExtraInfos > 0) {
|
if (allExtraInfos > 0) {
|
||||||
sb.append(String.format(", %d/%d E (%.1f%%)", foundExtraInfos,
|
sb.append(String.format(", %d/%d E (%.1f%%)", foundExtraInfos,
|
||||||
allExtraInfos, 100.0D * (double) foundExtraInfos /
|
allExtraInfos, 100.0D * (double) foundExtraInfos
|
||||||
(double) allExtraInfos));
|
/ (double) allExtraInfos));
|
||||||
} else {
|
} else {
|
||||||
sb.append(", 0/0 E");
|
sb.append(", 0/0 E");
|
||||||
}
|
}
|
||||||
@ -712,17 +729,17 @@ public class ArchiveWriter extends Thread {
|
|||||||
if (allMicrodescriptors > 0) {
|
if (allMicrodescriptors > 0) {
|
||||||
sb.append(String.format(", %d/%d M (%.1f%%)",
|
sb.append(String.format(", %d/%d M (%.1f%%)",
|
||||||
foundMicrodescriptors, allMicrodescriptors,
|
foundMicrodescriptors, allMicrodescriptors,
|
||||||
100.0D * (double) foundMicrodescriptors /
|
100.0D * (double) foundMicrodescriptors
|
||||||
(double) allMicrodescriptors));
|
/ (double) allMicrodescriptors));
|
||||||
} else {
|
} else {
|
||||||
sb.append(", 0/0 M");
|
sb.append(", 0/0 M");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
missingMicrodescConsensus = true;
|
missingMicrodescConsensus = true;
|
||||||
}
|
}
|
||||||
if (foundServerDescs * 1000 < allServerDescs * 995 ||
|
if (foundServerDescs * 1000 < allServerDescs * 995
|
||||||
foundExtraInfos * 1000 < allExtraInfos * 995 ||
|
|| foundExtraInfos * 1000 < allExtraInfos * 995
|
||||||
foundMicrodescriptors * 1000 < allMicrodescriptors * 995) {
|
|| foundMicrodescriptors * 1000 < allMicrodescriptors * 995) {
|
||||||
missingDescriptors = true;
|
missingDescriptors = true;
|
||||||
}
|
}
|
||||||
if (foundVotes < allVotes) {
|
if (foundVotes < allVotes) {
|
||||||
@ -756,44 +773,44 @@ public class ArchiveWriter extends Thread {
|
|||||||
"yyyy-MM-dd HH:mm:ss");
|
"yyyy-MM-dd HH:mm:ss");
|
||||||
dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||||
long tooOldMillis = this.now - 330L * 60L * 1000L;
|
long tooOldMillis = this.now - 330L * 60L * 1000L;
|
||||||
if (!this.storedConsensuses.isEmpty() &&
|
if (!this.storedConsensuses.isEmpty()
|
||||||
this.storedConsensuses.lastKey() < tooOldMillis) {
|
&& this.storedConsensuses.lastKey() < tooOldMillis) {
|
||||||
this.logger.warning("The last known relay network status "
|
this.logger.warning("The last known relay network status "
|
||||||
+ "consensus was valid after "
|
+ "consensus was valid after "
|
||||||
+ dateTimeFormat.format(this.storedConsensuses.lastKey())
|
+ dateTimeFormat.format(this.storedConsensuses.lastKey())
|
||||||
+ ", which is more than 5:30 hours in the past.");
|
+ ", which is more than 5:30 hours in the past.");
|
||||||
}
|
}
|
||||||
if (!this.storedMicrodescConsensuses.isEmpty() &&
|
if (!this.storedMicrodescConsensuses.isEmpty()
|
||||||
this.storedMicrodescConsensuses.lastKey() < tooOldMillis) {
|
&& this.storedMicrodescConsensuses.lastKey() < tooOldMillis) {
|
||||||
this.logger.warning("The last known relay network status "
|
this.logger.warning("The last known relay network status "
|
||||||
+ "microdesc consensus was valid after "
|
+ "microdesc consensus was valid after "
|
||||||
+ dateTimeFormat.format(
|
+ dateTimeFormat.format(
|
||||||
this.storedMicrodescConsensuses.lastKey())
|
this.storedMicrodescConsensuses.lastKey())
|
||||||
+ ", which is more than 5:30 hours in the past.");
|
+ ", which is more than 5:30 hours in the past.");
|
||||||
}
|
}
|
||||||
if (!this.storedVotes.isEmpty() &&
|
if (!this.storedVotes.isEmpty()
|
||||||
this.storedVotes.lastKey() < tooOldMillis) {
|
&& this.storedVotes.lastKey() < tooOldMillis) {
|
||||||
this.logger.warning("The last known relay network status vote "
|
this.logger.warning("The last known relay network status vote "
|
||||||
+ "was valid after " + dateTimeFormat.format(
|
+ "was valid after " + dateTimeFormat.format(
|
||||||
this.storedVotes.lastKey()) + ", which is more than 5:30 hours "
|
this.storedVotes.lastKey()) + ", which is more than 5:30 hours "
|
||||||
+ "in the past.");
|
+ "in the past.");
|
||||||
}
|
}
|
||||||
if (!this.storedServerDescriptors.isEmpty() &&
|
if (!this.storedServerDescriptors.isEmpty()
|
||||||
this.storedServerDescriptors.lastKey() < tooOldMillis) {
|
&& this.storedServerDescriptors.lastKey() < tooOldMillis) {
|
||||||
this.logger.warning("The last known relay server descriptor was "
|
this.logger.warning("The last known relay server descriptor was "
|
||||||
+ "published at "
|
+ "published at "
|
||||||
+ dateTimeFormat.format(this.storedServerDescriptors.lastKey())
|
+ dateTimeFormat.format(this.storedServerDescriptors.lastKey())
|
||||||
+ ", which is more than 5:30 hours in the past.");
|
+ ", which is more than 5:30 hours in the past.");
|
||||||
}
|
}
|
||||||
if (!this.storedExtraInfoDescriptors.isEmpty() &&
|
if (!this.storedExtraInfoDescriptors.isEmpty()
|
||||||
this.storedExtraInfoDescriptors.lastKey() < tooOldMillis) {
|
&& this.storedExtraInfoDescriptors.lastKey() < tooOldMillis) {
|
||||||
this.logger.warning("The last known relay extra-info descriptor "
|
this.logger.warning("The last known relay extra-info descriptor "
|
||||||
+ "was published at " + dateTimeFormat.format(
|
+ "was published at " + dateTimeFormat.format(
|
||||||
this.storedExtraInfoDescriptors.lastKey())
|
this.storedExtraInfoDescriptors.lastKey())
|
||||||
+ ", which is more than 5:30 hours in the past.");
|
+ ", which is more than 5:30 hours in the past.");
|
||||||
}
|
}
|
||||||
if (!this.storedMicrodescriptors.isEmpty() &&
|
if (!this.storedMicrodescriptors.isEmpty()
|
||||||
this.storedMicrodescriptors.lastKey() < tooOldMillis) {
|
&& this.storedMicrodescriptors.lastKey() < tooOldMillis) {
|
||||||
this.logger.warning("The last known relay microdescriptor was "
|
this.logger.warning("The last known relay microdescriptor was "
|
||||||
+ "contained in a microdesc consensus that was valid after "
|
+ "contained in a microdesc consensus that was valid after "
|
||||||
+ dateTimeFormat.format(this.storedMicrodescriptors.lastKey())
|
+ dateTimeFormat.format(this.storedMicrodescriptors.lastKey())
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
/* Copyright 2010--2012 The Tor Project
|
/* Copyright 2010--2016 The Tor Project
|
||||||
* See LICENSE for licensing information */
|
* See LICENSE for licensing information */
|
||||||
|
|
||||||
package org.torproject.collector.relaydescs;
|
package org.torproject.collector.relaydescs;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Hex;
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
@ -25,9 +29,6 @@ import java.util.TreeSet;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Hex;
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses all descriptors in local directory cacheddesc/ and sorts them
|
* Parses all descriptors in local directory cacheddesc/ and sorts them
|
||||||
* into directory structure in directory-archive/.
|
* into directory structure in directory-archive/.
|
||||||
@ -36,8 +37,8 @@ public class CachedRelayDescriptorReader {
|
|||||||
public CachedRelayDescriptorReader(RelayDescriptorParser rdp,
|
public CachedRelayDescriptorReader(RelayDescriptorParser rdp,
|
||||||
List<String> inputDirectories, File statsDirectory) {
|
List<String> inputDirectories, File statsDirectory) {
|
||||||
|
|
||||||
if (rdp == null || inputDirectories == null ||
|
if (rdp == null || inputDirectories == null
|
||||||
inputDirectories.isEmpty() || statsDirectory == null) {
|
|| inputDirectories.isEmpty() || statsDirectory == null) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,8 +49,8 @@ public class CachedRelayDescriptorReader {
|
|||||||
|
|
||||||
/* Read import history containing SHA-1 digests of previously parsed
|
/* Read import history containing SHA-1 digests of previously parsed
|
||||||
* statuses and descriptors, so that we can skip them in this run. */
|
* statuses and descriptors, so that we can skip them in this run. */
|
||||||
Set<String> lastImportHistory = new HashSet<String>(),
|
Set<String> lastImportHistory = new HashSet<String>();
|
||||||
currentImportHistory = new HashSet<String>();
|
Set<String> currentImportHistory = new HashSet<String>();
|
||||||
File importHistoryFile = new File(statsDirectory,
|
File importHistoryFile = new File(statsDirectory,
|
||||||
"cacheddesc-import-history");
|
"cacheddesc-import-history");
|
||||||
if (importHistoryFile.exists()) {
|
if (importHistoryFile.exists()) {
|
||||||
@ -114,8 +115,8 @@ public class CachedRelayDescriptorReader {
|
|||||||
SimpleDateFormat dateTimeFormat =
|
SimpleDateFormat dateTimeFormat =
|
||||||
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||||
if (dateTimeFormat.parse(line.substring("valid-after ".
|
if (dateTimeFormat.parse(line.substring("valid-after "
|
||||||
length())).getTime() < System.currentTimeMillis()
|
.length())).getTime() < System.currentTimeMillis()
|
||||||
- 6L * 60L * 60L * 1000L) {
|
- 6L * 60L * 60L * 1000L) {
|
||||||
logger.warning("Cached descriptor files in "
|
logger.warning("Cached descriptor files in "
|
||||||
+ cachedDescDir.getAbsolutePath() + " are stale. "
|
+ cachedDescDir.getAbsolutePath() + " are stale. "
|
||||||
@ -133,8 +134,8 @@ public class CachedRelayDescriptorReader {
|
|||||||
if (rdp != null) {
|
if (rdp != null) {
|
||||||
String digest = Hex.encodeHexString(DigestUtils.sha(
|
String digest = Hex.encodeHexString(DigestUtils.sha(
|
||||||
allData));
|
allData));
|
||||||
if (!lastImportHistory.contains(digest) &&
|
if (!lastImportHistory.contains(digest)
|
||||||
!currentImportHistory.contains(digest)) {
|
&& !currentImportHistory.contains(digest)) {
|
||||||
rdp.parse(allData);
|
rdp.parse(allData);
|
||||||
} else {
|
} else {
|
||||||
dumpStats.append(" (skipped)");
|
dumpStats.append(" (skipped)");
|
||||||
@ -142,7 +143,8 @@ public class CachedRelayDescriptorReader {
|
|||||||
currentImportHistory.add(digest);
|
currentImportHistory.add(digest);
|
||||||
}
|
}
|
||||||
} else if (f.getName().equals("v3-status-votes")) {
|
} else if (f.getName().equals("v3-status-votes")) {
|
||||||
int parsedNum = 0, skippedNum = 0;
|
int parsedNum = 0;
|
||||||
|
int skippedNum = 0;
|
||||||
String ascii = new String(allData, "US-ASCII");
|
String ascii = new String(allData, "US-ASCII");
|
||||||
String startToken = "network-status-version ";
|
String startToken = "network-status-version ";
|
||||||
int end = ascii.length();
|
int end = ascii.length();
|
||||||
@ -159,8 +161,8 @@ public class CachedRelayDescriptorReader {
|
|||||||
if (rdp != null) {
|
if (rdp != null) {
|
||||||
String digest = Hex.encodeHexString(DigestUtils.sha(
|
String digest = Hex.encodeHexString(DigestUtils.sha(
|
||||||
rawNetworkStatusBytes));
|
rawNetworkStatusBytes));
|
||||||
if (!lastImportHistory.contains(digest) &&
|
if (!lastImportHistory.contains(digest)
|
||||||
!currentImportHistory.contains(digest)) {
|
&& !currentImportHistory.contains(digest)) {
|
||||||
rdp.parse(rawNetworkStatusBytes);
|
rdp.parse(rawNetworkStatusBytes);
|
||||||
parsedNum++;
|
parsedNum++;
|
||||||
} else {
|
} else {
|
||||||
@ -173,16 +175,19 @@ public class CachedRelayDescriptorReader {
|
|||||||
}
|
}
|
||||||
dumpStats.append("\n" + f.getName() + ": parsed " + parsedNum
|
dumpStats.append("\n" + f.getName() + ": parsed " + parsedNum
|
||||||
+ ", skipped " + skippedNum + " votes");
|
+ ", skipped " + skippedNum + " votes");
|
||||||
} else if (f.getName().startsWith("cached-descriptors") ||
|
} else if (f.getName().startsWith("cached-descriptors")
|
||||||
f.getName().startsWith("cached-extrainfo")) {
|
|| f.getName().startsWith("cached-extrainfo")) {
|
||||||
String ascii = new String(allData, "US-ASCII");
|
String ascii = new String(allData, "US-ASCII");
|
||||||
int start = -1, sig = -1, end = -1;
|
int start = -1;
|
||||||
|
int sig = -1;
|
||||||
|
int end = -1;
|
||||||
String startToken =
|
String startToken =
|
||||||
f.getName().startsWith("cached-descriptors") ?
|
f.getName().startsWith("cached-descriptors")
|
||||||
"router " : "extra-info ";
|
? "router " : "extra-info ";
|
||||||
String sigToken = "\nrouter-signature\n";
|
String sigToken = "\nrouter-signature\n";
|
||||||
String endToken = "\n-----END SIGNATURE-----\n";
|
String endToken = "\n-----END SIGNATURE-----\n";
|
||||||
int parsedNum = 0, skippedNum = 0;
|
int parsedNum = 0;
|
||||||
|
int skippedNum = 0;
|
||||||
while (end < ascii.length()) {
|
while (end < ascii.length()) {
|
||||||
start = ascii.indexOf(startToken, end);
|
start = ascii.indexOf(startToken, end);
|
||||||
if (start < 0) {
|
if (start < 0) {
|
||||||
@ -203,8 +208,8 @@ public class CachedRelayDescriptorReader {
|
|||||||
if (rdp != null) {
|
if (rdp != null) {
|
||||||
String digest = Hex.encodeHexString(DigestUtils.sha(
|
String digest = Hex.encodeHexString(DigestUtils.sha(
|
||||||
descBytes));
|
descBytes));
|
||||||
if (!lastImportHistory.contains(digest) &&
|
if (!lastImportHistory.contains(digest)
|
||||||
!currentImportHistory.contains(digest)) {
|
&& !currentImportHistory.contains(digest)) {
|
||||||
rdp.parse(descBytes);
|
rdp.parse(descBytes);
|
||||||
parsedNum++;
|
parsedNum++;
|
||||||
} else {
|
} else {
|
||||||
@ -215,8 +220,8 @@ public class CachedRelayDescriptorReader {
|
|||||||
}
|
}
|
||||||
dumpStats.append("\n" + f.getName() + ": parsed " + parsedNum
|
dumpStats.append("\n" + f.getName() + ": parsed " + parsedNum
|
||||||
+ ", skipped " + skippedNum + " "
|
+ ", skipped " + skippedNum + " "
|
||||||
+ (f.getName().startsWith("cached-descriptors") ?
|
+ (f.getName().startsWith("cached-descriptors")
|
||||||
"server" : "extra-info") + " descriptors");
|
? "server" : "extra-info") + " descriptors");
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.log(Level.WARNING, "Failed reading "
|
logger.log(Level.WARNING, "Failed reading "
|
||||||
|
@ -1,5 +1,22 @@
|
|||||||
|
/* Copyright 2016 The Tor Project
|
||||||
|
* See LICENSE for licensing information */
|
||||||
|
|
||||||
package org.torproject.collector.relaydescs;
|
package org.torproject.collector.relaydescs;
|
||||||
|
|
||||||
|
import org.torproject.descriptor.Descriptor;
|
||||||
|
import org.torproject.descriptor.DescriptorFile;
|
||||||
|
import org.torproject.descriptor.DescriptorReader;
|
||||||
|
import org.torproject.descriptor.DescriptorSourceFactory;
|
||||||
|
import org.torproject.descriptor.DirSourceEntry;
|
||||||
|
import org.torproject.descriptor.ExtraInfoDescriptor;
|
||||||
|
import org.torproject.descriptor.Microdescriptor;
|
||||||
|
import org.torproject.descriptor.NetworkStatusEntry;
|
||||||
|
import org.torproject.descriptor.RelayNetworkStatusConsensus;
|
||||||
|
import org.torproject.descriptor.RelayNetworkStatusVote;
|
||||||
|
import org.torproject.descriptor.ServerDescriptor;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
@ -17,20 +34,6 @@ import java.util.TreeSet;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.torproject.descriptor.Descriptor;
|
|
||||||
import org.torproject.descriptor.DescriptorFile;
|
|
||||||
import org.torproject.descriptor.DescriptorReader;
|
|
||||||
import org.torproject.descriptor.DescriptorSourceFactory;
|
|
||||||
import org.torproject.descriptor.DirSourceEntry;
|
|
||||||
import org.torproject.descriptor.ExtraInfoDescriptor;
|
|
||||||
import org.torproject.descriptor.Microdescriptor;
|
|
||||||
import org.torproject.descriptor.NetworkStatusEntry;
|
|
||||||
import org.torproject.descriptor.RelayNetworkStatusConsensus;
|
|
||||||
import org.torproject.descriptor.RelayNetworkStatusVote;
|
|
||||||
import org.torproject.descriptor.ServerDescriptor;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
|
|
||||||
public class ReferenceChecker {
|
public class ReferenceChecker {
|
||||||
|
|
||||||
private Logger log = Logger.getLogger(ReferenceChecker.class.getName());
|
private Logger log = Logger.getLogger(ReferenceChecker.class.getName());
|
||||||
@ -87,8 +90,8 @@ public class ReferenceChecker {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Reference other = (Reference) otherObject;
|
Reference other = (Reference) otherObject;
|
||||||
return this.referencing.equals(other.referencing) &&
|
return this.referencing.equals(other.referencing)
|
||||||
this.referenced.equals(other.referenced);
|
&& this.referenced.equals(other.referenced);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -168,6 +171,7 @@ public class ReferenceChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static DateFormat dateTimeFormat;
|
private static DateFormat dateTimeFormat;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'",
|
dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||||
Locale.US);
|
Locale.US);
|
||||||
@ -175,9 +179,15 @@ public class ReferenceChecker {
|
|||||||
dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final long ONE_HOUR = 60L * 60L * 1000L,
|
private static final long ONE_HOUR = 60L * 60L * 1000L;
|
||||||
THREE_HOURS = 3L * ONE_HOUR, SIX_HOURS = 6L * ONE_HOUR,
|
|
||||||
ONE_DAY = 24L * ONE_HOUR, THIRTY_DAYS = 30L * ONE_DAY;
|
private static final long THREE_HOURS = 3L * ONE_HOUR;
|
||||||
|
|
||||||
|
private static final long SIX_HOURS = 6L * ONE_HOUR;
|
||||||
|
|
||||||
|
private static final long ONE_DAY = 24L * ONE_HOUR;
|
||||||
|
|
||||||
|
private static final long THIRTY_DAYS = 30L * ONE_DAY;
|
||||||
|
|
||||||
private void readRelayNetworkStatusConsensusUnflavored(
|
private void readRelayNetworkStatusConsensusUnflavored(
|
||||||
RelayNetworkStatusConsensus consensus) {
|
RelayNetworkStatusConsensus consensus) {
|
||||||
@ -194,8 +204,8 @@ public class ReferenceChecker {
|
|||||||
consensus.getValidAfterMillis() + THREE_HOURS);
|
consensus.getValidAfterMillis() + THREE_HOURS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
double entryWeight = 200.0 /
|
double entryWeight = 200.0
|
||||||
((double) consensus.getStatusEntries().size());
|
/ ((double) consensus.getStatusEntries().size());
|
||||||
for (NetworkStatusEntry entry :
|
for (NetworkStatusEntry entry :
|
||||||
consensus.getStatusEntries().values()) {
|
consensus.getStatusEntries().values()) {
|
||||||
this.addReference(referencing,
|
this.addReference(referencing,
|
||||||
@ -212,8 +222,8 @@ public class ReferenceChecker {
|
|||||||
String referencing = String.format("M-%s", validAfter);
|
String referencing = String.format("M-%s", validAfter);
|
||||||
this.addReference(referencing, String.format("C-%s", validAfter), 1.0,
|
this.addReference(referencing, String.format("C-%s", validAfter), 1.0,
|
||||||
consensus.getValidAfterMillis() + THREE_HOURS);
|
consensus.getValidAfterMillis() + THREE_HOURS);
|
||||||
double entryWeight = 200.0 /
|
double entryWeight = 200.0
|
||||||
((double) consensus.getStatusEntries().size());
|
/ ((double) consensus.getStatusEntries().size());
|
||||||
for (NetworkStatusEntry entry :
|
for (NetworkStatusEntry entry :
|
||||||
consensus.getStatusEntries().values()) {
|
consensus.getStatusEntries().values()) {
|
||||||
for (String digest : entry.getMicrodescriptorDigests()) {
|
for (String digest : entry.getMicrodescriptorDigests()) {
|
||||||
@ -227,8 +237,8 @@ public class ReferenceChecker {
|
|||||||
String validAfter = dateTimeFormat.format(vote.getValidAfterMillis());
|
String validAfter = dateTimeFormat.format(vote.getValidAfterMillis());
|
||||||
String referencing = String.format("V-%s-%s", validAfter,
|
String referencing = String.format("V-%s-%s", validAfter,
|
||||||
vote.getIdentity());
|
vote.getIdentity());
|
||||||
double entryWeight = 200.0 /
|
double entryWeight = 200.0
|
||||||
((double) vote.getStatusEntries().size());
|
/ ((double) vote.getStatusEntries().size());
|
||||||
for (NetworkStatusEntry entry : vote.getStatusEntries().values()) {
|
for (NetworkStatusEntry entry : vote.getStatusEntries().values()) {
|
||||||
this.addReference(referencing,
|
this.addReference(referencing,
|
||||||
String.format("S-%s", entry.getDescriptor()), entryWeight,
|
String.format("S-%s", entry.getDescriptor()), entryWeight,
|
||||||
@ -277,8 +287,8 @@ public class ReferenceChecker {
|
|||||||
StringBuilder sb = new StringBuilder("Missing referenced "
|
StringBuilder sb = new StringBuilder("Missing referenced "
|
||||||
+ "descriptors:");
|
+ "descriptors:");
|
||||||
for (Reference reference : this.references) {
|
for (Reference reference : this.references) {
|
||||||
if (reference.referenced.length() > 0 &&
|
if (reference.referenced.length() > 0
|
||||||
!knownDescriptors.contains(reference.referenced)) {
|
&& !knownDescriptors.contains(reference.referenced)) {
|
||||||
if (!missingDescriptors.contains(reference.referenced)) {
|
if (!missingDescriptors.contains(reference.referenced)) {
|
||||||
totalMissingDescriptorsWeight += reference.weight;
|
totalMissingDescriptorsWeight += reference.weight;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
/* Copyright 2010--2014 The Tor Project
|
/* Copyright 2010--2016 The Tor Project
|
||||||
* See LICENSE for licensing information */
|
* See LICENSE for licensing information */
|
||||||
|
|
||||||
package org.torproject.collector.relaydescs;
|
package org.torproject.collector.relaydescs;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
@ -31,9 +35,6 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.zip.InflaterInputStream;
|
import java.util.zip.InflaterInputStream;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Downloads relay descriptors from the directory authorities via HTTP.
|
* Downloads relay descriptors from the directory authorities via HTTP.
|
||||||
* Keeps a list of missing descriptors that gets updated by parse results
|
* Keeps a list of missing descriptors that gets updated by parse results
|
||||||
@ -224,25 +225,61 @@ public class RelayDescriptorDownloader {
|
|||||||
* that we requested, and that we successfully downloaded in this
|
* that we requested, and that we successfully downloaded in this
|
||||||
* execution.
|
* execution.
|
||||||
*/
|
*/
|
||||||
private int oldMissingConsensuses = 0,
|
private int oldMissingConsensuses = 0;
|
||||||
oldMissingMicrodescConsensuses = 0, oldMissingVotes = 0,
|
|
||||||
oldMissingServerDescriptors = 0, oldMissingExtraInfoDescriptors = 0,
|
private int oldMissingMicrodescConsensuses = 0;
|
||||||
oldMissingMicrodescriptors = 0, newMissingConsensuses = 0,
|
|
||||||
newMissingMicrodescConsensuses = 0, newMissingVotes = 0,
|
private int oldMissingVotes = 0;
|
||||||
newMissingServerDescriptors = 0, newMissingExtraInfoDescriptors = 0,
|
|
||||||
newMissingMicrodescriptors = 0, requestedConsensuses = 0,
|
private int oldMissingServerDescriptors = 0;
|
||||||
requestedMicrodescConsensuses = 0, requestedVotes = 0,
|
|
||||||
requestedMissingServerDescriptors = 0,
|
private int oldMissingExtraInfoDescriptors = 0;
|
||||||
requestedAllServerDescriptors = 0,
|
|
||||||
requestedMissingExtraInfoDescriptors = 0,
|
private int oldMissingMicrodescriptors = 0;
|
||||||
requestedAllExtraInfoDescriptors = 0,
|
|
||||||
requestedMissingMicrodescriptors = 0, downloadedConsensuses = 0,
|
private int newMissingConsensuses = 0;
|
||||||
downloadedMicrodescConsensuses = 0, downloadedVotes = 0,
|
|
||||||
downloadedMissingServerDescriptors = 0,
|
private int newMissingMicrodescConsensuses = 0;
|
||||||
downloadedAllServerDescriptors = 0,
|
|
||||||
downloadedMissingExtraInfoDescriptors = 0,
|
private int newMissingVotes = 0;
|
||||||
downloadedAllExtraInfoDescriptors = 0,
|
|
||||||
downloadedMissingMicrodescriptors = 0;
|
private int newMissingServerDescriptors = 0;
|
||||||
|
|
||||||
|
private int newMissingExtraInfoDescriptors = 0;
|
||||||
|
|
||||||
|
private int newMissingMicrodescriptors = 0;
|
||||||
|
|
||||||
|
private int requestedConsensuses = 0;
|
||||||
|
|
||||||
|
private int requestedMicrodescConsensuses = 0;
|
||||||
|
|
||||||
|
private int requestedVotes = 0;
|
||||||
|
|
||||||
|
private int requestedMissingServerDescriptors = 0;
|
||||||
|
|
||||||
|
private int requestedAllServerDescriptors = 0;
|
||||||
|
|
||||||
|
private int requestedMissingExtraInfoDescriptors = 0;
|
||||||
|
|
||||||
|
private int requestedAllExtraInfoDescriptors = 0;
|
||||||
|
|
||||||
|
private int requestedMissingMicrodescriptors = 0;
|
||||||
|
|
||||||
|
private int downloadedConsensuses = 0;
|
||||||
|
|
||||||
|
private int downloadedMicrodescConsensuses = 0;
|
||||||
|
|
||||||
|
private int downloadedVotes = 0;
|
||||||
|
|
||||||
|
private int downloadedMissingServerDescriptors = 0;
|
||||||
|
|
||||||
|
private int downloadedAllServerDescriptors = 0;
|
||||||
|
|
||||||
|
private int downloadedMissingExtraInfoDescriptors = 0;
|
||||||
|
|
||||||
|
private int downloadedAllExtraInfoDescriptors = 0;
|
||||||
|
|
||||||
|
private int downloadedMissingMicrodescriptors = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes this class, including reading in missing descriptors from
|
* Initializes this class, including reading in missing descriptors from
|
||||||
@ -292,8 +329,8 @@ public class RelayDescriptorDownloader {
|
|||||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
format.setTimeZone(TimeZone.getTimeZone("UTC"));
|
format.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
this.currentValidAfter = format.format((now / (60L * 60L * 1000L)) *
|
this.currentValidAfter = format.format((now / (60L * 60L * 1000L))
|
||||||
(60L * 60L * 1000L));
|
* (60L * 60L * 1000L));
|
||||||
this.descriptorCutOff = format.format(now - 24L * 60L * 60L * 1000L);
|
this.descriptorCutOff = format.format(now - 24L * 60L * 60L * 1000L);
|
||||||
this.currentTimestamp = format.format(now);
|
this.currentTimestamp = format.format(now);
|
||||||
this.downloadAllDescriptorsCutOff = format.format(now
|
this.downloadAllDescriptorsCutOff = format.format(now
|
||||||
@ -317,14 +354,14 @@ public class RelayDescriptorDownloader {
|
|||||||
while ((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
if (line.split(",").length > 2) {
|
if (line.split(",").length > 2) {
|
||||||
String published = line.split(",")[1];
|
String published = line.split(",")[1];
|
||||||
if (((line.startsWith("consensus,") ||
|
if (((line.startsWith("consensus,")
|
||||||
line.startsWith("consensus-microdesc,") ||
|
|| line.startsWith("consensus-microdesc,")
|
||||||
line.startsWith("vote,")) &&
|
|| line.startsWith("vote,"))
|
||||||
this.currentValidAfter.equals(published)) ||
|
&& this.currentValidAfter.equals(published))
|
||||||
((line.startsWith("server,") ||
|
|| ((line.startsWith("server,")
|
||||||
line.startsWith("extra,") ||
|
|| line.startsWith("extra,")
|
||||||
line.startsWith("micro,")) &&
|
|| line.startsWith("micro,"))
|
||||||
this.descriptorCutOff.compareTo(published) < 0)) {
|
&& this.descriptorCutOff.compareTo(published) < 0)) {
|
||||||
if (!line.endsWith("NA")) {
|
if (!line.endsWith("NA")) {
|
||||||
/* Not missing. */
|
/* Not missing. */
|
||||||
} else if (line.startsWith("consensus,")) {
|
} else if (line.startsWith("consensus,")) {
|
||||||
@ -352,8 +389,8 @@ public class RelayDescriptorDownloader {
|
|||||||
}
|
}
|
||||||
this.microdescriptorKeys.get(microdescriptorDigest).add(
|
this.microdescriptorKeys.get(microdescriptorDigest).add(
|
||||||
microdescriptorKey);
|
microdescriptorKey);
|
||||||
if (line.endsWith("NA") && !this.missingMicrodescriptors.
|
if (line.endsWith("NA") && !this.missingMicrodescriptors
|
||||||
contains(microdescriptorDigest)) {
|
.contains(microdescriptorDigest)) {
|
||||||
this.missingMicrodescriptors.add(microdescriptorDigest);
|
this.missingMicrodescriptors.add(microdescriptorDigest);
|
||||||
oldMissingMicrodescriptors++;
|
oldMissingMicrodescriptors++;
|
||||||
}
|
}
|
||||||
@ -418,8 +455,8 @@ public class RelayDescriptorDownloader {
|
|||||||
* download all server and extra-info descriptors from. */
|
* download all server and extra-info descriptors from. */
|
||||||
this.downloadAllDescriptorsFromAuthorities = new HashSet<String>();
|
this.downloadAllDescriptorsFromAuthorities = new HashSet<String>();
|
||||||
for (String authority : this.authorities) {
|
for (String authority : this.authorities) {
|
||||||
if (!this.lastDownloadedAllDescriptors.containsKey(authority) ||
|
if (!this.lastDownloadedAllDescriptors.containsKey(authority)
|
||||||
this.lastDownloadedAllDescriptors.get(authority).compareTo(
|
|| this.lastDownloadedAllDescriptors.get(authority).compareTo(
|
||||||
this.downloadAllDescriptorsCutOff) < 0) {
|
this.downloadAllDescriptorsCutOff) < 0) {
|
||||||
this.downloadAllDescriptorsFromAuthorities.add(authority);
|
this.downloadAllDescriptorsFromAuthorities.add(authority);
|
||||||
}
|
}
|
||||||
@ -523,8 +560,8 @@ public class RelayDescriptorDownloader {
|
|||||||
this.microdescriptorKeys.get(microdescriptorDigest).add(
|
this.microdescriptorKeys.get(microdescriptorDigest).add(
|
||||||
microdescriptorKey);
|
microdescriptorKey);
|
||||||
this.missingDescriptors.put(microdescriptorKey, parsed);
|
this.missingDescriptors.put(microdescriptorKey, parsed);
|
||||||
if (parsed.equals("NA") &&
|
if (parsed.equals("NA")
|
||||||
!this.missingMicrodescriptors.contains(microdescriptorDigest)) {
|
&& !this.missingMicrodescriptors.contains(microdescriptorDigest)) {
|
||||||
this.missingMicrodescriptors.add(microdescriptorDigest);
|
this.missingMicrodescriptors.add(microdescriptorDigest);
|
||||||
this.newMissingMicrodescriptors++;
|
this.newMissingMicrodescriptors++;
|
||||||
}
|
}
|
||||||
@ -662,8 +699,8 @@ public class RelayDescriptorDownloader {
|
|||||||
/* Start with downloading the current consensus, unless we already
|
/* Start with downloading the current consensus, unless we already
|
||||||
* have it. */
|
* have it. */
|
||||||
if (downloadCurrentConsensus) {
|
if (downloadCurrentConsensus) {
|
||||||
if (this.missingDescriptors.containsKey(consensusKey) &&
|
if (this.missingDescriptors.containsKey(consensusKey)
|
||||||
this.missingDescriptors.get(consensusKey).equals("NA")) {
|
&& this.missingDescriptors.get(consensusKey).equals("NA")) {
|
||||||
this.requestedConsensuses++;
|
this.requestedConsensuses++;
|
||||||
this.downloadedConsensuses +=
|
this.downloadedConsensuses +=
|
||||||
this.downloadResourceFromAuthority(authority,
|
this.downloadResourceFromAuthority(authority,
|
||||||
@ -673,10 +710,9 @@ public class RelayDescriptorDownloader {
|
|||||||
|
|
||||||
/* Then try to download the microdesc consensus. */
|
/* Then try to download the microdesc consensus. */
|
||||||
if (downloadCurrentMicrodescConsensus) {
|
if (downloadCurrentMicrodescConsensus) {
|
||||||
if (this.missingDescriptors.containsKey(
|
if (this.missingDescriptors.containsKey(microdescConsensusKey)
|
||||||
microdescConsensusKey) &&
|
&& this.missingDescriptors.get(microdescConsensusKey)
|
||||||
this.missingDescriptors.get(microdescConsensusKey).
|
.equals("NA")) {
|
||||||
equals("NA")) {
|
|
||||||
this.requestedMicrodescConsensuses++;
|
this.requestedMicrodescConsensuses++;
|
||||||
this.downloadedMicrodescConsensuses +=
|
this.downloadedMicrodescConsensuses +=
|
||||||
this.downloadResourceFromAuthority(authority,
|
this.downloadResourceFromAuthority(authority,
|
||||||
@ -690,8 +726,8 @@ public class RelayDescriptorDownloader {
|
|||||||
SortedSet<String> fingerprints = new TreeSet<String>();
|
SortedSet<String> fingerprints = new TreeSet<String>();
|
||||||
for (Map.Entry<String, String> e :
|
for (Map.Entry<String, String> e :
|
||||||
this.missingDescriptors.entrySet()) {
|
this.missingDescriptors.entrySet()) {
|
||||||
if (e.getValue().equals("NA") &&
|
if (e.getValue().equals("NA")
|
||||||
e.getKey().startsWith(voteKeyPrefix)) {
|
&& e.getKey().startsWith(voteKeyPrefix)) {
|
||||||
String fingerprint = e.getKey().split(",")[2];
|
String fingerprint = e.getKey().split(",")[2];
|
||||||
fingerprints.add(fingerprint);
|
fingerprints.add(fingerprint);
|
||||||
}
|
}
|
||||||
@ -714,9 +750,9 @@ public class RelayDescriptorDownloader {
|
|||||||
* authority if we haven't done so for 24 hours and if we're
|
* authority if we haven't done so for 24 hours and if we're
|
||||||
* configured to do so. */
|
* configured to do so. */
|
||||||
if (this.downloadAllDescriptorsFromAuthorities.contains(
|
if (this.downloadAllDescriptorsFromAuthorities.contains(
|
||||||
authority) && ((type.equals("server") &&
|
authority) && ((type.equals("server")
|
||||||
this.downloadAllServerDescriptors) ||
|
&& this.downloadAllServerDescriptors)
|
||||||
(type.equals("extra") && this.downloadAllExtraInfos))) {
|
|| (type.equals("extra") && this.downloadAllExtraInfos))) {
|
||||||
int downloadedAllDescriptors =
|
int downloadedAllDescriptors =
|
||||||
this.downloadResourceFromAuthority(authority, "/tor/"
|
this.downloadResourceFromAuthority(authority, "/tor/"
|
||||||
+ type + "/all");
|
+ type + "/all");
|
||||||
@ -732,11 +768,11 @@ public class RelayDescriptorDownloader {
|
|||||||
|
|
||||||
/* Download missing server descriptors, extra-info descriptors,
|
/* Download missing server descriptors, extra-info descriptors,
|
||||||
* and microdescriptors if we're configured to do so. */
|
* and microdescriptors if we're configured to do so. */
|
||||||
} else if ((type.equals("server") &&
|
} else if ((type.equals("server")
|
||||||
this.downloadMissingServerDescriptors) ||
|
&& this.downloadMissingServerDescriptors)
|
||||||
(type.equals("extra") && this.downloadMissingExtraInfos) ||
|
|| (type.equals("extra") && this.downloadMissingExtraInfos)
|
||||||
(type.equals("micro") &&
|
|| (type.equals("micro")
|
||||||
this.downloadMissingMicrodescriptors)) {
|
&& this.downloadMissingMicrodescriptors)) {
|
||||||
|
|
||||||
/* Go through the list of missing descriptors of this type
|
/* Go through the list of missing descriptors of this type
|
||||||
* and combine the descriptor identifiers to a URL of up to
|
* and combine the descriptor identifiers to a URL of up to
|
||||||
@ -746,23 +782,24 @@ public class RelayDescriptorDownloader {
|
|||||||
new TreeSet<String>();
|
new TreeSet<String>();
|
||||||
for (Map.Entry<String, String> e :
|
for (Map.Entry<String, String> e :
|
||||||
this.missingDescriptors.entrySet()) {
|
this.missingDescriptors.entrySet()) {
|
||||||
if (e.getValue().equals("NA") &&
|
if (e.getValue().equals("NA")
|
||||||
e.getKey().startsWith(type + ",") &&
|
&& e.getKey().startsWith(type + ",")
|
||||||
this.descriptorCutOff.compareTo(
|
&& this.descriptorCutOff.compareTo(
|
||||||
e.getKey().split(",")[1]) < 0) {
|
e.getKey().split(",")[1]) < 0) {
|
||||||
String descriptorIdentifier = e.getKey().split(",")[3];
|
String descriptorIdentifier = e.getKey().split(",")[3];
|
||||||
descriptorIdentifiers.add(descriptorIdentifier);
|
descriptorIdentifiers.add(descriptorIdentifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StringBuilder combinedResource = null;
|
StringBuilder combinedResource = null;
|
||||||
int descriptorsInCombinedResource = 0,
|
int descriptorsInCombinedResource = 0;
|
||||||
requestedDescriptors = 0, downloadedDescriptors = 0;
|
int requestedDescriptors = 0;
|
||||||
|
int downloadedDescriptors = 0;
|
||||||
int maxDescriptorsInCombinedResource =
|
int maxDescriptorsInCombinedResource =
|
||||||
type.equals("micro") ? 92 : 96;
|
type.equals("micro") ? 92 : 96;
|
||||||
String separator = type.equals("micro") ? "-" : "+";
|
String separator = type.equals("micro") ? "-" : "+";
|
||||||
for (String descriptorIdentifier : descriptorIdentifiers) {
|
for (String descriptorIdentifier : descriptorIdentifiers) {
|
||||||
if (descriptorsInCombinedResource >=
|
if (descriptorsInCombinedResource
|
||||||
maxDescriptorsInCombinedResource) {
|
>= maxDescriptorsInCombinedResource) {
|
||||||
requestedDescriptors += descriptorsInCombinedResource;
|
requestedDescriptors += descriptorsInCombinedResource;
|
||||||
downloadedDescriptors +=
|
downloadedDescriptors +=
|
||||||
this.downloadResourceFromAuthority(authority,
|
this.downloadResourceFromAuthority(authority,
|
||||||
@ -836,8 +873,8 @@ public class RelayDescriptorDownloader {
|
|||||||
huc.connect();
|
huc.connect();
|
||||||
int response = huc.getResponseCode();
|
int response = huc.getResponseCode();
|
||||||
if (response == 200) {
|
if (response == 200) {
|
||||||
BufferedInputStream in = this.downloadCompressed &&
|
BufferedInputStream in = this.downloadCompressed
|
||||||
!resource.startsWith("/tor/extra/")
|
&& !resource.startsWith("/tor/extra/")
|
||||||
? new BufferedInputStream(new InflaterInputStream(
|
? new BufferedInputStream(new InflaterInputStream(
|
||||||
huc.getInputStream()))
|
huc.getInputStream()))
|
||||||
: new BufferedInputStream(huc.getInputStream());
|
: new BufferedInputStream(huc.getInputStream());
|
||||||
@ -857,10 +894,10 @@ public class RelayDescriptorDownloader {
|
|||||||
if (resource.startsWith("/tor/status-vote/current/")) {
|
if (resource.startsWith("/tor/status-vote/current/")) {
|
||||||
this.rdp.parse(allData);
|
this.rdp.parse(allData);
|
||||||
receivedDescriptors = 1;
|
receivedDescriptors = 1;
|
||||||
} else if (resource.startsWith("/tor/server/") ||
|
} else if (resource.startsWith("/tor/server/")
|
||||||
resource.startsWith("/tor/extra/")) {
|
|| resource.startsWith("/tor/extra/")) {
|
||||||
if (resource.equals("/tor/server/all") ||
|
if (resource.equals("/tor/server/all")
|
||||||
resource.equals("/tor/extra/all")) {
|
|| resource.equals("/tor/extra/all")) {
|
||||||
this.lastDownloadedAllDescriptors.put(authority,
|
this.lastDownloadedAllDescriptors.put(authority,
|
||||||
this.currentTimestamp);
|
this.currentTimestamp);
|
||||||
}
|
}
|
||||||
@ -870,9 +907,11 @@ public class RelayDescriptorDownloader {
|
|||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
/* No way that US-ASCII is not supported. */
|
/* No way that US-ASCII is not supported. */
|
||||||
}
|
}
|
||||||
int start = -1, sig = -1, end = -1;
|
int start = -1;
|
||||||
String startToken = resource.startsWith("/tor/server/") ?
|
int sig = -1;
|
||||||
"router " : "extra-info ";
|
int end = -1;
|
||||||
|
String startToken = resource.startsWith("/tor/server/")
|
||||||
|
? "router " : "extra-info ";
|
||||||
String sigToken = "\nrouter-signature\n";
|
String sigToken = "\nrouter-signature\n";
|
||||||
String endToken = "\n-----END SIGNATURE-----\n";
|
String endToken = "\n-----END SIGNATURE-----\n";
|
||||||
while (end < ascii.length()) {
|
while (end < ascii.length()) {
|
||||||
@ -910,7 +949,8 @@ public class RelayDescriptorDownloader {
|
|||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
/* No way that US-ASCII is not supported. */
|
/* No way that US-ASCII is not supported. */
|
||||||
}
|
}
|
||||||
int start = -1, end = -1;
|
int start = -1;
|
||||||
|
int end = -1;
|
||||||
String startToken = "onion-key\n";
|
String startToken = "onion-key\n";
|
||||||
while (end < ascii.length()) {
|
while (end < ascii.length()) {
|
||||||
start = ascii.indexOf(startToken, end);
|
start = ascii.indexOf(startToken, end);
|
||||||
@ -961,9 +1001,11 @@ public class RelayDescriptorDownloader {
|
|||||||
public void writeFile() {
|
public void writeFile() {
|
||||||
|
|
||||||
/* Write missing descriptors file to disk. */
|
/* Write missing descriptors file to disk. */
|
||||||
int missingConsensuses = 0, missingMicrodescConsensuses = 0,
|
int missingConsensuses = 0;
|
||||||
missingVotes = 0, missingServerDescriptors = 0,
|
int missingMicrodescConsensuses = 0;
|
||||||
missingExtraInfoDescriptors = 0;
|
int missingVotes = 0;
|
||||||
|
int missingServerDescriptors = 0;
|
||||||
|
int missingExtraInfoDescriptors = 0;
|
||||||
try {
|
try {
|
||||||
this.logger.fine("Writing file "
|
this.logger.fine("Writing file "
|
||||||
+ this.missingDescriptorsFile.getAbsolutePath() + "...");
|
+ this.missingDescriptorsFile.getAbsolutePath() + "...");
|
||||||
@ -972,7 +1014,8 @@ public class RelayDescriptorDownloader {
|
|||||||
this.missingDescriptorsFile));
|
this.missingDescriptorsFile));
|
||||||
for (Map.Entry<String, String> e :
|
for (Map.Entry<String, String> e :
|
||||||
this.missingDescriptors.entrySet()) {
|
this.missingDescriptors.entrySet()) {
|
||||||
String key = e.getKey(), value = e.getValue();
|
String key = e.getKey();
|
||||||
|
String value = e.getValue();
|
||||||
if (!value.equals("NA")) {
|
if (!value.equals("NA")) {
|
||||||
/* Not missing. */
|
/* Not missing. */
|
||||||
} else if (key.startsWith("consensus,")) {
|
} else if (key.startsWith("consensus,")) {
|
||||||
@ -986,6 +1029,7 @@ public class RelayDescriptorDownloader {
|
|||||||
} else if (key.startsWith("extra,")) {
|
} else if (key.startsWith("extra,")) {
|
||||||
missingExtraInfoDescriptors++;
|
missingExtraInfoDescriptors++;
|
||||||
} else if (key.startsWith("micro,")) {
|
} else if (key.startsWith("micro,")) {
|
||||||
|
/* We're counting missing microdescriptors below. */
|
||||||
}
|
}
|
||||||
bw.write(key + "," + value + "\n");
|
bw.write(key + "," + value + "\n");
|
||||||
}
|
}
|
||||||
@ -1059,7 +1103,7 @@ public class RelayDescriptorDownloader {
|
|||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (String authority : this.authorities) {
|
for (String authority : this.authorities) {
|
||||||
sb.append(" " + authority + "="
|
sb.append(" " + authority + "="
|
||||||
+ this.requestsByAuthority.get(authority));
|
+ this.requestsByAuthority.get(authority));
|
||||||
}
|
}
|
||||||
this.logger.info("We sent these numbers of requests to the directory "
|
this.logger.info("We sent these numbers of requests to the directory "
|
||||||
+ "authorities:" + sb.toString());
|
+ "authorities:" + sb.toString());
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
/* Copyright 2010--2014 The Tor Project
|
/* Copyright 2010--2016 The Tor Project
|
||||||
* See LICENSE for licensing information */
|
* See LICENSE for licensing information */
|
||||||
|
|
||||||
package org.torproject.collector.relaydescs;
|
package org.torproject.collector.relaydescs;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.commons.codec.binary.Hex;
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
@ -13,10 +18,6 @@ import java.util.TreeSet;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
|
||||||
import org.apache.commons.codec.binary.Hex;
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses relay descriptors including network status consensuses and
|
* Parses relay descriptors including network status consensuses and
|
||||||
* votes, server and extra-info descriptors, and passes the results to the
|
* votes, server and extra-info descriptors, and passes the results to the
|
||||||
@ -93,9 +94,11 @@ public class RelayDescriptorParser {
|
|||||||
if (line.equals("network-status-version 3 microdesc")) {
|
if (line.equals("network-status-version 3 microdesc")) {
|
||||||
statusType = "consensus-microdesc";
|
statusType = "consensus-microdesc";
|
||||||
}
|
}
|
||||||
String validAfterTime = null, fingerprint = null,
|
String validAfterTime = null;
|
||||||
dirSource = null;
|
String fingerprint = null;
|
||||||
long validAfter = -1L, dirKeyPublished = -1L;
|
String dirSource = null;
|
||||||
|
long validAfter = -1L;
|
||||||
|
long dirKeyPublished = -1L;
|
||||||
SortedSet<String> dirSources = new TreeSet<String>();
|
SortedSet<String> dirSources = new TreeSet<String>();
|
||||||
SortedSet<String> serverDescriptors = new TreeSet<String>();
|
SortedSet<String> serverDescriptors = new TreeSet<String>();
|
||||||
SortedSet<String> serverDescriptorDigests = new TreeSet<String>();
|
SortedSet<String> serverDescriptorDigests = new TreeSet<String>();
|
||||||
@ -130,8 +133,8 @@ public class RelayDescriptorParser {
|
|||||||
} else if (line.startsWith("dir-key-published ")) {
|
} else if (line.startsWith("dir-key-published ")) {
|
||||||
String dirKeyPublishedTime = line.substring(
|
String dirKeyPublishedTime = line.substring(
|
||||||
"dir-key-published ".length());
|
"dir-key-published ".length());
|
||||||
dirKeyPublished = parseFormat.parse(dirKeyPublishedTime).
|
dirKeyPublished = parseFormat.parse(dirKeyPublishedTime)
|
||||||
getTime();
|
.getTime();
|
||||||
} else if (line.startsWith("r ")) {
|
} else if (line.startsWith("r ")) {
|
||||||
String[] parts = line.split(" ");
|
String[] parts = line.split(" ");
|
||||||
if (parts.length == 8) {
|
if (parts.length == 8) {
|
||||||
@ -158,12 +161,12 @@ public class RelayDescriptorParser {
|
|||||||
microdescriptorKeys.add(validAfterTime + ","
|
microdescriptorKeys.add(validAfterTime + ","
|
||||||
+ lastRelayIdentity + "," + digest256Base64);
|
+ lastRelayIdentity + "," + digest256Base64);
|
||||||
String digest256Hex = Hex.encodeHexString(
|
String digest256Hex = Hex.encodeHexString(
|
||||||
Base64.decodeBase64(digest256Base64 + "=")).
|
Base64.decodeBase64(digest256Base64 + "="))
|
||||||
toLowerCase();
|
.toLowerCase();
|
||||||
microdescriptorDigests.add(digest256Hex);
|
microdescriptorDigests.add(digest256Hex);
|
||||||
} else if (parts.length != 3 ||
|
} else if (parts.length != 3
|
||||||
!parts[2].startsWith("sha256=") ||
|
|| !parts[2].startsWith("sha256=")
|
||||||
parts[2].length() != 50) {
|
|| parts[2].length() != 50) {
|
||||||
this.logger.log(Level.WARNING, "Could not parse m line '"
|
this.logger.log(Level.WARNING, "Could not parse m line '"
|
||||||
+ line + "' in descriptor. Skipping.");
|
+ line + "' in descriptor. Skipping.");
|
||||||
break;
|
break;
|
||||||
@ -226,23 +229,24 @@ public class RelayDescriptorParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (line.startsWith("router ")) {
|
} else if (line.startsWith("router ")) {
|
||||||
String publishedTime = null, extraInfoDigest = null,
|
String publishedTime = null;
|
||||||
relayIdentifier = null;
|
String extraInfoDigest = null;
|
||||||
|
String relayIdentifier = null;
|
||||||
long published = -1L;
|
long published = -1L;
|
||||||
while ((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
if (line.startsWith("published ")) {
|
if (line.startsWith("published ")) {
|
||||||
publishedTime = line.substring("published ".length());
|
publishedTime = line.substring("published ".length());
|
||||||
published = parseFormat.parse(publishedTime).getTime();
|
published = parseFormat.parse(publishedTime).getTime();
|
||||||
} else if (line.startsWith("opt fingerprint") ||
|
} else if (line.startsWith("opt fingerprint")
|
||||||
line.startsWith("fingerprint")) {
|
|| line.startsWith("fingerprint")) {
|
||||||
relayIdentifier = line.substring(line.startsWith("opt ") ?
|
relayIdentifier = line.substring(line.startsWith("opt ")
|
||||||
"opt fingerprint".length() : "fingerprint".length()).
|
? "opt fingerprint".length() : "fingerprint".length())
|
||||||
replaceAll(" ", "").toLowerCase();
|
.replaceAll(" ", "").toLowerCase();
|
||||||
} else if (line.startsWith("opt extra-info-digest ") ||
|
} else if (line.startsWith("opt extra-info-digest ")
|
||||||
line.startsWith("extra-info-digest ")) {
|
|| line.startsWith("extra-info-digest ")) {
|
||||||
extraInfoDigest = line.startsWith("opt ") ?
|
extraInfoDigest = line.startsWith("opt ")
|
||||||
line.split(" ")[2].toLowerCase() :
|
? line.split(" ")[2].toLowerCase()
|
||||||
line.split(" ")[1].toLowerCase();
|
: line.split(" ")[1].toLowerCase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String ascii = new String(data, "US-ASCII");
|
String ascii = new String(data, "US-ASCII");
|
||||||
@ -266,7 +270,8 @@ public class RelayDescriptorParser {
|
|||||||
relayIdentifier, digest, extraInfoDigest);
|
relayIdentifier, digest, extraInfoDigest);
|
||||||
}
|
}
|
||||||
} else if (line.startsWith("extra-info ")) {
|
} else if (line.startsWith("extra-info ")) {
|
||||||
String publishedTime = null, relayIdentifier = line.split(" ")[2];
|
String publishedTime = null;
|
||||||
|
String relayIdentifier = line.split(" ")[2];
|
||||||
long published = -1L;
|
long published = -1L;
|
||||||
while ((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
if (line.startsWith("published ")) {
|
if (line.startsWith("published ")) {
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
/* Copyright 2012-2016 The Tor Project
|
/* Copyright 2012-2016 The Tor Project
|
||||||
* See LICENSE for licensing information */
|
* See LICENSE for licensing information */
|
||||||
|
|
||||||
package org.torproject.collector.torperf;
|
package org.torproject.collector.torperf;
|
||||||
|
|
||||||
|
import org.torproject.collector.main.Configuration;
|
||||||
|
import org.torproject.collector.main.LockFile;
|
||||||
|
import org.torproject.collector.main.LoggingConfiguration;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -22,10 +27,6 @@ import java.util.TreeMap;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.torproject.collector.main.Configuration;
|
|
||||||
import org.torproject.collector.main.LockFile;
|
|
||||||
import org.torproject.collector.main.LoggingConfiguration;
|
|
||||||
|
|
||||||
/* Download possibly truncated Torperf .data and .extradata files from
|
/* Download possibly truncated Torperf .data and .extradata files from
|
||||||
* configured sources, append them to the files we already have, and merge
|
* configured sources, append them to the files we already have, and merge
|
||||||
* the two files into the .tpf format. */
|
* the two files into the .tpf format. */
|
||||||
@ -97,8 +98,10 @@ public class TorperfDownloader extends Thread {
|
|||||||
|
|
||||||
private File torperfLastMergedFile =
|
private File torperfLastMergedFile =
|
||||||
new File("stats/torperf-last-merged");
|
new File("stats/torperf-last-merged");
|
||||||
|
|
||||||
SortedMap<String, String> lastMergedTimestamps =
|
SortedMap<String, String> lastMergedTimestamps =
|
||||||
new TreeMap<String, String>();
|
new TreeMap<String, String>();
|
||||||
|
|
||||||
private void readLastMergedTimestamps() {
|
private void readLastMergedTimestamps() {
|
||||||
if (!this.torperfLastMergedFile.exists()) {
|
if (!this.torperfLastMergedFile.exists()) {
|
||||||
return;
|
return;
|
||||||
@ -109,7 +112,8 @@ public class TorperfDownloader extends Thread {
|
|||||||
String line;
|
String line;
|
||||||
while ((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
String[] parts = line.split(" ");
|
String[] parts = line.split(" ");
|
||||||
String fileName = null, timestamp = null;
|
String fileName = null;
|
||||||
|
String timestamp = null;
|
||||||
if (parts.length == 2) {
|
if (parts.length == 2) {
|
||||||
try {
|
try {
|
||||||
Double.parseDouble(parts[1]);
|
Double.parseDouble(parts[1]);
|
||||||
@ -315,11 +319,14 @@ public class TorperfDownloader extends Thread {
|
|||||||
}
|
}
|
||||||
this.logger.fine("Merging " + dataFile.getAbsolutePath() + " and "
|
this.logger.fine("Merging " + dataFile.getAbsolutePath() + " and "
|
||||||
+ extradataFile.getAbsolutePath() + " into .tpf format.");
|
+ extradataFile.getAbsolutePath() + " into .tpf format.");
|
||||||
BufferedReader brD = new BufferedReader(new FileReader(dataFile)),
|
BufferedReader brD = new BufferedReader(new FileReader(dataFile));
|
||||||
brE = new BufferedReader(new FileReader(extradataFile));
|
BufferedReader brE = new BufferedReader(new FileReader(extradataFile));
|
||||||
String lineD = brD.readLine(), lineE = brE.readLine();
|
String lineD = brD.readLine();
|
||||||
int d = 1, e = 1;
|
String lineE = brE.readLine();
|
||||||
String maxDataComplete = null, maxUsedAt = null;
|
int d = 1;
|
||||||
|
int e = 1;
|
||||||
|
String maxDataComplete = null;
|
||||||
|
String maxUsedAt = null;
|
||||||
while (lineD != null) {
|
while (lineD != null) {
|
||||||
|
|
||||||
/* Parse .data line. Every valid .data line will go into the .tpf
|
/* Parse .data line. Every valid .data line will go into the .tpf
|
||||||
@ -363,8 +370,8 @@ public class TorperfDownloader extends Thread {
|
|||||||
+ e++ + " which is a BUILDTIMEOUT_SET line.");
|
+ e++ + " which is a BUILDTIMEOUT_SET line.");
|
||||||
lineE = brE.readLine();
|
lineE = brE.readLine();
|
||||||
continue;
|
continue;
|
||||||
} else if (lineE.startsWith("ok ") ||
|
} else if (lineE.startsWith("ok ")
|
||||||
lineE.startsWith("error ")) {
|
|| lineE.startsWith("error ")) {
|
||||||
this.logger.finer("Skipping " + extradataFile.getName() + ":"
|
this.logger.finer("Skipping " + extradataFile.getName() + ":"
|
||||||
+ e++ + " which is in the old format.");
|
+ e++ + " which is in the old format.");
|
||||||
lineE = brE.readLine();
|
lineE = brE.readLine();
|
||||||
@ -446,6 +453,7 @@ public class TorperfDownloader extends Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private SortedMap<Integer, String> dataTimestamps;
|
private SortedMap<Integer, String> dataTimestamps;
|
||||||
|
|
||||||
private SortedMap<String, String> parseDataLine(String line) {
|
private SortedMap<String, String> parseDataLine(String line) {
|
||||||
String[] parts = line.trim().split(" ");
|
String[] parts = line.trim().split(" ");
|
||||||
if (line.length() == 0 || parts.length < 20) {
|
if (line.length() == 0 || parts.length < 20) {
|
||||||
@ -504,18 +512,18 @@ public class TorperfDownloader extends Thread {
|
|||||||
String key = keyAndValue[0];
|
String key = keyAndValue[0];
|
||||||
previousKey = key;
|
previousKey = key;
|
||||||
String value = keyAndValue[1];
|
String value = keyAndValue[1];
|
||||||
if (value.contains(".") && value.lastIndexOf(".") ==
|
if (value.contains(".") && value.lastIndexOf(".")
|
||||||
value.length() - 2) {
|
== value.length() - 2) {
|
||||||
/* Make sure that all floats have two trailing digits. */
|
/* Make sure that all floats have two trailing digits. */
|
||||||
value += "0";
|
value += "0";
|
||||||
}
|
}
|
||||||
extradata.put(key, value);
|
extradata.put(key, value);
|
||||||
} else if (keyAndValue.length == 1 && previousKey != null) {
|
} else if (keyAndValue.length == 1 && previousKey != null) {
|
||||||
String value = keyAndValue[0];
|
String value = keyAndValue[0];
|
||||||
if (previousKey.equals("STREAM_FAIL_REASONS") &&
|
if (previousKey.equals("STREAM_FAIL_REASONS")
|
||||||
(value.equals("MISC") || value.equals("EXITPOLICY") ||
|
&& (value.equals("MISC") || value.equals("EXITPOLICY")
|
||||||
value.equals("RESOURCELIMIT") ||
|
|| value.equals("RESOURCELIMIT")
|
||||||
value.equals("RESOLVEFAILED"))) {
|
|| value.equals("RESOLVEFAILED"))) {
|
||||||
extradata.put(previousKey, extradata.get(previousKey) + ":"
|
extradata.put(previousKey, extradata.get(previousKey) + ":"
|
||||||
+ value);
|
+ value);
|
||||||
} else {
|
} else {
|
||||||
@ -529,9 +537,13 @@ public class TorperfDownloader extends Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String cachedSource;
|
private String cachedSource;
|
||||||
|
|
||||||
private int cachedFileSize;
|
private int cachedFileSize;
|
||||||
|
|
||||||
private String cachedStartDate;
|
private String cachedStartDate;
|
||||||
|
|
||||||
private SortedMap<String, String> cachedTpfLines;
|
private SortedMap<String, String> cachedTpfLines;
|
||||||
|
|
||||||
private void writeTpfLine(String source, int fileSize,
|
private void writeTpfLine(String source, int fileSize,
|
||||||
SortedMap<String, String> keysAndValues) throws IOException {
|
SortedMap<String, String> keysAndValues) throws IOException {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
@ -547,14 +559,14 @@ public class TorperfDownloader extends Thread {
|
|||||||
long startMillis = Long.parseLong(startString.substring(0,
|
long startMillis = Long.parseLong(startString.substring(0,
|
||||||
startString.indexOf("."))) * 1000L;
|
startString.indexOf("."))) * 1000L;
|
||||||
String startDate = dateFormat.format(startMillis);
|
String startDate = dateFormat.format(startMillis);
|
||||||
if (this.cachedTpfLines == null || !source.equals(this.cachedSource) ||
|
if (this.cachedTpfLines == null || !source.equals(this.cachedSource)
|
||||||
fileSize != this.cachedFileSize ||
|
|| fileSize != this.cachedFileSize
|
||||||
!startDate.equals(this.cachedStartDate)) {
|
|| !startDate.equals(this.cachedStartDate)) {
|
||||||
this.writeCachedTpfLines();
|
this.writeCachedTpfLines();
|
||||||
this.readTpfLinesToCache(source, fileSize, startDate);
|
this.readTpfLinesToCache(source, fileSize, startDate);
|
||||||
}
|
}
|
||||||
if (!this.cachedTpfLines.containsKey(startString) ||
|
if (!this.cachedTpfLines.containsKey(startString)
|
||||||
line.length() > this.cachedTpfLines.get(startString).length()) {
|
|| line.length() > this.cachedTpfLines.get(startString).length()) {
|
||||||
this.cachedTpfLines.put(startString, line);
|
this.cachedTpfLines.put(startString, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -588,8 +600,8 @@ public class TorperfDownloader extends Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void writeCachedTpfLines() throws IOException {
|
private void writeCachedTpfLines() throws IOException {
|
||||||
if (this.cachedSource == null || this.cachedFileSize == 0 ||
|
if (this.cachedSource == null || this.cachedFileSize == 0
|
||||||
this.cachedStartDate == null || this.cachedTpfLines == null) {
|
|| this.cachedStartDate == null || this.cachedTpfLines == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
File tarballFile = new File(torperfOutputDirectory,
|
File tarballFile = new File(torperfOutputDirectory,
|
||||||
|
Loading…
Reference in New Issue
Block a user