tor-commits
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 1 participants
- 214893 discussions
commit 1619c2cf49ddbe485511376b2483f7c0bb249f4c
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Tue Dec 13 11:04:39 2011 +0100
Add a missing word.
---
.../torproject/doctor/MetricsWebsiteReport.java | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/org/torproject/doctor/MetricsWebsiteReport.java b/src/org/torproject/doctor/MetricsWebsiteReport.java
index 1529461..f4552e0 100755
--- a/src/org/torproject/doctor/MetricsWebsiteReport.java
+++ b/src/org/torproject/doctor/MetricsWebsiteReport.java
@@ -163,8 +163,8 @@ public class MetricsWebsiteReport {
this.bw.write(dateTimeFormat.format(
this.downloadedConsensus.getValidAfterMillis()));
}
- this.bw.write(". <i>Note that it takes up to 15 to learn about new "
- + "consensus and votes and process them.</i></p>\n");
+ this.bw.write(". <i>Note that it takes up to 15 minutes to learn "
+ + "about new consensus and votes and process them.</i></p>\n");
}
/* Write the lists of known flags. */
1
0
[doctor/master] Rely on metrics-lib to parse consensuses and votes.
by karsten@torproject.org 13 Dec '11
by karsten@torproject.org 13 Dec '11
13 Dec '11
commit ad912387e433d29726eefcaca301967f4ce50427
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Tue Dec 13 10:18:07 2011 +0100
Rely on metrics-lib to parse consensuses and votes.
---
src/org/torproject/doctor/Checker.java | 91 ++++++---
src/org/torproject/doctor/Download.java | 46 -----
src/org/torproject/doctor/DownloadStatistics.java | 25 ++-
src/org/torproject/doctor/Downloader.java | 62 ++-----
src/org/torproject/doctor/Main.java | 52 ++----
.../torproject/doctor/MetricsWebsiteReport.java | 139 ++++++++------
src/org/torproject/doctor/Parser.java | 180 -----------------
src/org/torproject/doctor/Report.java | 27 ---
src/org/torproject/doctor/Status.java | 205 --------------------
src/org/torproject/doctor/StatusEntry.java | 48 -----
src/org/torproject/doctor/StatusFileReport.java | 17 +--
11 files changed, 194 insertions(+), 698 deletions(-)
diff --git a/src/org/torproject/doctor/Checker.java b/src/org/torproject/doctor/Checker.java
index 4d6493f..ee4e29e 100755
--- a/src/org/torproject/doctor/Checker.java
+++ b/src/org/torproject/doctor/Checker.java
@@ -5,6 +5,7 @@ package org.torproject.doctor;
import java.io.*;
import java.text.*;
import java.util.*;
+import org.torproject.descriptor.*;
/* Check a given consensus and votes for irregularities and write results
* to a warnings map consisting of warning type and details. */
@@ -26,12 +27,15 @@ public class Checker {
}
/* Downloaded consensus and corresponding votes for processing. */
- private SortedMap<String, Status> downloadedConsensuses;
- private Status downloadedConsensus;
- private SortedSet<Status> downloadedVotes;
+ private SortedMap<String, RelayNetworkStatusConsensus>
+ downloadedConsensuses = new TreeMap<String,
+ RelayNetworkStatusConsensus>();
+ private RelayNetworkStatusConsensus downloadedConsensus;
+ private List<RelayNetworkStatusVote> downloadedVotes =
+ new ArrayList<RelayNetworkStatusVote>();
public void processDownloadedConsensuses(
- SortedMap<String, Status> downloadedConsensuses) {
- this.downloadedConsensuses = downloadedConsensuses;
+ List<DescriptorRequest> downloads) {
+ this.storeDownloads(downloads);
this.findMostRecentConsensus();
this.checkMissingConsensuses();
this.checkAllConsensusesFresh();
@@ -51,10 +55,29 @@ public class Checker {
}
}
+ /* Store consensuses and votes in a way that we can process them more
+ * easily. */
+ private void storeDownloads(List<DescriptorRequest> downloads) {
+ for (DescriptorRequest request : downloads) {
+ for (Descriptor descriptor : request.getDescriptors()) {
+ if (descriptor instanceof RelayNetworkStatusConsensus) {
+ this.downloadedConsensuses.put(request.getDirectoryNickname(),
+ (RelayNetworkStatusConsensus) descriptor);
+ } else if (descriptor instanceof RelayNetworkStatusVote) {
+ this.downloadedVotes.add((RelayNetworkStatusVote) descriptor);
+ } else {
+ System.err.println("Did not expect a descriptor of type "
+ + descriptor.getClass() + ". Ignoring.");
+ }
+ }
+ }
+ }
+
/* Find most recent consensus and corresponding votes. */
private void findMostRecentConsensus() {
long mostRecentValidAfterMillis = -1L;
- for (Status downloadedConsensus : downloadedConsensuses.values()) {
+ for (RelayNetworkStatusConsensus downloadedConsensus :
+ downloadedConsensuses.values()) {
if (downloadedConsensus.getValidAfterMillis() >
mostRecentValidAfterMillis) {
this.downloadedConsensus = downloadedConsensus;
@@ -62,9 +85,6 @@ public class Checker {
downloadedConsensus.getValidAfterMillis();
}
}
- if (this.downloadedConsensus != null) {
- this.downloadedVotes = this.downloadedConsensus.getVotes();
- }
}
/* Check if any directory authority didn't tell us a consensus. */
@@ -87,9 +107,10 @@ public class Checker {
private void checkAllConsensusesFresh() {
long fresh = System.currentTimeMillis() - 60L * 60L * 1000L;
SortedSet<String> nonFresh = new TreeSet<String>();
- for (Map.Entry<String, Status> e : downloadedConsensuses.entrySet()) {
+ for (Map.Entry<String, RelayNetworkStatusConsensus> e :
+ downloadedConsensuses.entrySet()) {
String nickname = e.getKey();
- Status downloadedConsensus = e.getValue();
+ RelayNetworkStatusConsensus downloadedConsensus = e.getValue();
if (downloadedConsensus.getValidAfterMillis() < fresh) {
nonFresh.add(nickname);
}
@@ -107,14 +128,16 @@ public class Checker {
/* Check if all downloaded consensuses contain the same set of votes. */
private void checkContainedVotes() {
Set<String> allVotes = new HashSet<String>();
- for (Status consensus : downloadedConsensuses.values()) {
- allVotes.addAll(consensus.getContainedVotes());
+ for (RelayNetworkStatusConsensus consensus :
+ downloadedConsensuses.values()) {
+ allVotes.addAll(consensus.getDirSourceEntries().keySet());
}
SortedSet<String> missingVotes = new TreeSet<String>();
- for (Map.Entry<String, Status> e : downloadedConsensuses.entrySet()) {
+ for (Map.Entry<String, RelayNetworkStatusConsensus> e :
+ downloadedConsensuses.entrySet()) {
String nickname = e.getKey();
- Status downloadedConsensus = e.getValue();
- if (!downloadedConsensus.getContainedVotes().containsAll(
+ RelayNetworkStatusConsensus downloadedConsensus = e.getValue();
+ if (!downloadedConsensus.getDirSourceEntries().keySet().containsAll(
allVotes)) {
missingVotes.add(nickname);
}
@@ -133,11 +156,13 @@ public class Checker {
* authorities. */
private void checkConsensusSignatures() {
SortedSet<String> missingSignatures = new TreeSet<String>();
- for (Map.Entry<String, Status> e : downloadedConsensuses.entrySet()) {
+ for (Map.Entry<String, RelayNetworkStatusConsensus> e :
+ downloadedConsensuses.entrySet()) {
String nickname = e.getKey();
- Status downloadedConsensus = e.getValue();
- if (!downloadedConsensus.getContainedSignatures().containsAll(
- downloadedConsensus.getContainedVotes())) {
+ RelayNetworkStatusConsensus downloadedConsensus = e.getValue();
+ if (!downloadedConsensus.getDirectorySignatures().keySet().
+ containsAll(downloadedConsensus.getDirSourceEntries().
+ keySet())) {
missingSignatures.add(nickname);
}
}
@@ -152,7 +177,8 @@ public class Checker {
}
/* Check if the most recent consensus is older than 1 hour. */
- private boolean isConsensusFresh(Status consensus) {
+ private boolean isConsensusFresh(
+ RelayNetworkStatusConsensus consensus) {
return (consensus.getValidAfterMillis() >=
System.currentTimeMillis() - 60L * 60L * 1000L);
}
@@ -160,9 +186,9 @@ public class Checker {
/* Check supported consensus methods of all votes. */
private void checkConsensusMethods() {
SortedSet<String> dirs = new TreeSet<String>();
- for (Status vote : this.downloadedVotes) {
+ for (RelayNetworkStatusVote vote : this.downloadedVotes) {
if (!vote.getConsensusMethods().contains(
- this.downloadedConsensus.getConsensusMethods().last())) {
+ this.downloadedConsensus.getConsensusMethod())) {
dirs.add(vote.getNickname());
}
}
@@ -181,7 +207,7 @@ public class Checker {
private void checkRecommendedVersions() {
SortedSet<String> unrecommendedClientVersions = new TreeSet<String>(),
unrecommendedServerVersions = new TreeSet<String>();
- for (Status vote : this.downloadedVotes) {
+ for (RelayNetworkStatusVote vote : this.downloadedVotes) {
if (vote.getRecommendedClientVersions() != null &&
!downloadedConsensus.getRecommendedClientVersions().equals(
vote.getRecommendedClientVersions())) {
@@ -231,7 +257,7 @@ public class Checker {
+ "cbtmintimeout,cbtinitialtimeout,perconnbwburst,perconnbwrate").
split(",")));
SortedSet<String> conflicts = new TreeSet<String>();
- for (Status vote : this.downloadedVotes) {
+ for (RelayNetworkStatusVote vote : this.downloadedVotes) {
Map<String, String> voteConsensusParams =
vote.getConsensusParams();
boolean conflictOrInvalid = false;
@@ -272,7 +298,7 @@ public class Checker {
SortedMap<String, String> expiringCertificates =
new TreeMap<String, String>();
long now = System.currentTimeMillis();
- for (Status vote : this.downloadedVotes) {
+ for (RelayNetworkStatusVote vote : this.downloadedVotes) {
long voteDirKeyExpiresMillis = vote.getDirKeyExpiresMillis();
if (voteDirKeyExpiresMillis - 14L * 24L * 60L * 60L * 1000L < now) {
expiringCertificates.put(vote.getNickname(),
@@ -299,7 +325,7 @@ public class Checker {
+ "tor26,urras").split(",")));
SortedSet<String> missingVotes =
new TreeSet<String>(knownAuthorities);
- for (Status vote : this.downloadedVotes) {
+ for (RelayNetworkStatusVote vote : this.downloadedVotes) {
missingVotes.remove(vote.getNickname());
}
if (!missingVotes.isEmpty()) {
@@ -316,8 +342,15 @@ public class Checker {
private void checkBandwidthScanners() {
SortedSet<String> missingBandwidthScanners = new TreeSet<String>(
Arrays.asList("ides,urras,moria1,gabelmoo,maatuska".split(",")));
- for (Status vote : this.downloadedVotes) {
- if (vote.getBandwidthWeights() > 0) {
+ for (RelayNetworkStatusVote vote : this.downloadedVotes) {
+ boolean containsMeasuredBandwidths = false;
+ for (NetworkStatusEntry entry : vote.getStatusEntries().values()) {
+ if (entry.getBandwidth().contains("Measured=")) {
+ containsMeasuredBandwidths = true;
+ break;
+ }
+ }
+ if (containsMeasuredBandwidths) {
missingBandwidthScanners.remove(vote.getNickname());
}
}
diff --git a/src/org/torproject/doctor/Download.java b/src/org/torproject/doctor/Download.java
deleted file mode 100644
index 5c84277..0000000
--- a/src/org/torproject/doctor/Download.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Copyright 2011 The Tor Project
- * See LICENSE for licensing information */
-package org.torproject.doctor;
-
-public class Download {
-
- /* Nickname of the authority from which this download was made. */
- private String authority;
- public String getAuthority() {
- return this.authority;
- }
-
- /* Request URL. */
- private String url;
- public String getUrl() {
- return this.url;
- }
-
- /* Unparsed response string. */
- private String responseString;
- public String getResponseString() {
- return this.responseString;
- }
-
- /* Request start timestamp. */
- private long requestStartMillis;
- public long getRequestStartMillis() {
- return this.requestStartMillis;
- }
-
- /* Fetch time in millis. */
- private long fetchTime;
- public long getFetchTime() {
- return this.fetchTime;
- }
-
- public Download(String authority, String url, String responseString,
- long requestStartMillis, long fetchTime) {
- this.authority = authority;
- this.url = url;
- this.responseString = responseString;
- this.requestStartMillis = requestStartMillis;
- this.fetchTime = fetchTime;
- }
-}
-
diff --git a/src/org/torproject/doctor/DownloadStatistics.java b/src/org/torproject/doctor/DownloadStatistics.java
index 9eeffde..9df0333 100644
--- a/src/org/torproject/doctor/DownloadStatistics.java
+++ b/src/org/torproject/doctor/DownloadStatistics.java
@@ -4,21 +4,26 @@ package org.torproject.doctor;
import java.io.*;
import java.util.*;
+import org.torproject.descriptor.*;
public class DownloadStatistics {
- public void memorizeFetchTimes(List<Download> downloadedConsensuses) {
+ public void memorizeFetchTimes(List<DescriptorRequest> downloads) {
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(
this.statisticsFile, true));
- for (Download downloadedConsensus : downloadedConsensuses) {
- String authority = downloadedConsensus.getAuthority();
- long requestStartMillis =
- downloadedConsensus.getRequestStartMillis();
- long fetchTimeMillis = downloadedConsensus.getFetchTime();
- String line = authority + ","
- + String.valueOf(requestStartMillis) + ","
- + String.valueOf(fetchTimeMillis);
- bw.write(line + "\n");
+ for (DescriptorRequest request : downloads) {
+ for (Descriptor descriptor : request.getDescriptors()) {
+ if (descriptor instanceof RelayNetworkStatusConsensus) {
+ String authority = request.getDirectoryNickname();
+ long requestStartMillis = request.getRequestStart();
+ long fetchTimeMillis = request.getRequestEnd()
+ - request.getRequestStart();
+ String line = authority + ","
+ + String.valueOf(requestStartMillis) + ","
+ + String.valueOf(fetchTimeMillis);
+ bw.write(line + "\n");
+ }
+ }
}
bw.close();
} catch (IOException e) {
diff --git a/src/org/torproject/doctor/Downloader.java b/src/org/torproject/doctor/Downloader.java
index a82ac8d..317b3b6 100755
--- a/src/org/torproject/doctor/Downloader.java
+++ b/src/org/torproject/doctor/Downloader.java
@@ -13,8 +13,8 @@ import org.torproject.descriptor.*;
* votes. */
public class Downloader {
- /* Download a new consensus and corresponding votes. */
- public void downloadFromAuthorities() {
+ /* Download the current consensus and corresponding votes. */
+ public List<DescriptorRequest> downloadFromAuthorities() {
RelayDescriptorDownloader downloader =
DescriptorSourceFactory.createRelayDescriptorDownloader();
@@ -33,58 +33,24 @@ public class Downloader {
downloader.setRequestTimeout(60L * 1000L);
+ List<DescriptorRequest> allRequests =
+ new ArrayList<DescriptorRequest>();
Iterator<DescriptorRequest> descriptorRequests =
downloader.downloadDescriptors();
while (descriptorRequests.hasNext()) {
- DescriptorRequest request = descriptorRequests.next();
- String authority = request.getDirectoryNickname();
- String requestUrl = request.getRequestUrl();
- long requestStart = request.getRequestStart();
- long fetchTime = request.getRequestEnd()
- - request.getRequestStart();
- if (request.globalTimeoutHasExpired()) {
- System.err.println("Global timeout has expired. Exiting.");
- System.exit(1);
- } else if (!request.requestTimeoutHasExpired()) {
- if (request.getDescriptors().isEmpty()) {
- /* No response. We'll realize later on if we're missing a
- * consensus or vote. */
- continue;
- } else if (request.getDescriptors().size() > 1) {
- System.out.println("Response contains more than 1 "
- + "descriptor. Considering only the first.");
- }
- Descriptor downloadedDescriptor = request.getDescriptors().get(0);
- String response = new String(request.getDescriptors().get(0).
- getRawDescriptorBytes());
- Download download = new Download(authority, requestUrl, response,
- requestStart, fetchTime);
- if (downloadedDescriptor instanceof
- RelayNetworkStatusConsensus) {
- this.downloadedConsensuses.add(download);
- } else if (downloadedDescriptor instanceof
- RelayNetworkStatusVote) {
- this.downloadedVotes.add(download);
- } else {
- System.err.println("Did not expect a descriptor of type "
- + downloadedDescriptor.getClass() + ". Ignoring.");
- }
+ try {
+ allRequests.add(descriptorRequests.next());
+ } catch (NoSuchElementException e) {
+ /* TODO In theory, this exception shouldn't be thrown. */
+ System.err.println("Internal error: next() doesn't provide an "
+ + "element even though hasNext() returned true. Got "
+ + allRequests.size() + " elements so far. Stopping to "
+ + "request further elements.");
+ break;
}
}
- }
-
- /* Return the previously downloaded (unparsed) consensus string by
- * authority nickname. */
- private List<Download> downloadedConsensuses =
- new ArrayList<Download>();
- public List<Download> getConsensuses() {
- return this.downloadedConsensuses;
- }
- /* Return the previously downloaded (unparsed) vote strings. */
- private List<Download> downloadedVotes = new ArrayList<Download>();
- public List<Download> getVotes() {
- return this.downloadedVotes;
+ return allRequests;
}
}
diff --git a/src/org/torproject/doctor/Main.java b/src/org/torproject/doctor/Main.java
index 0de6298..40973b4 100755
--- a/src/org/torproject/doctor/Main.java
+++ b/src/org/torproject/doctor/Main.java
@@ -3,53 +3,37 @@
package org.torproject.doctor;
import java.util.*;
+import org.torproject.descriptor.*;
/* Coordinate the process of downloading consensus and votes to check
* Tor's consensus health. */
public class Main {
public static void main(String[] args) {
- /* Initialize reports. */
- List<Report> reports = new ArrayList<Report>();
- reports.add(new MetricsWebsiteReport(
- "website/consensus-health.html"));
- reports.add(new StatusFileReport());
-
/* Download consensus and corresponding votes from the directory
* authorities. */
Downloader downloader = new Downloader();
- downloader.downloadFromAuthorities();
- List<Download> downloadedConsensuses = downloader.getConsensuses();
- List<Download> downloadedVotes = downloader.getVotes();
-
- /* Write fetch times for requesting consensuses to disk and prepare
- * statistics about fetch times in the last 7 days. */
- DownloadStatistics fetchStatistics = new DownloadStatistics();
- fetchStatistics.memorizeFetchTimes(downloadedConsensuses);
- fetchStatistics.prepareStatistics();
+ List<DescriptorRequest> downloads =
+ downloader.downloadFromAuthorities();
- /* Parse consensus and votes. */
- Parser parser = new Parser();
- SortedMap<String, Status> parsedDownloadedConsensuses = parser.parse(
- downloadedConsensuses, downloadedVotes);
-
- /* Check consensus and votes for possible problems. */
+ /* Check consensus and votes for possible problems and write warnings
+ * to status files. */
+ StatusFileReport statusFile = new StatusFileReport();
Checker checker = new Checker();
- checker.processDownloadedConsensuses(parsedDownloadedConsensuses);
+ checker.processDownloadedConsensuses(downloads);
SortedMap<Warning, String> warnings = checker.getWarnings();
+ statusFile.processWarnings(warnings);
+ statusFile.writeReport();
- /* Pass warnings, consensuses, and votes to the reports, and finish
- * writing them. */
- for (Report report : reports) {
- report.processWarnings(warnings);
- report.processDownloadedConsensuses(parsedDownloadedConsensuses);
- report.includeFetchStatistics(fetchStatistics);
- report.writeReport();
- }
-
- /* Terminate the program including any download threads that may still
- * be running. */
- System.exit(0);
+ /* Write a complete consensus-health report to an HTML file. */
+ MetricsWebsiteReport website =
+ new MetricsWebsiteReport("website/consensus-health.html");
+ website.processDownloadedConsensuses(downloads);
+ DownloadStatistics fetchStatistics = new DownloadStatistics();
+ fetchStatistics.memorizeFetchTimes(downloads);
+ fetchStatistics.prepareStatistics();
+ website.includeFetchStatistics(fetchStatistics);
+ website.writeReport();
}
}
diff --git a/src/org/torproject/doctor/MetricsWebsiteReport.java b/src/org/torproject/doctor/MetricsWebsiteReport.java
index 9ae897a..1529461 100755
--- a/src/org/torproject/doctor/MetricsWebsiteReport.java
+++ b/src/org/torproject/doctor/MetricsWebsiteReport.java
@@ -5,10 +5,11 @@ package org.torproject.doctor;
import java.io.*;
import java.text.*;
import java.util.*;
+import org.torproject.descriptor.*;
/* Transform the most recent consensus and corresponding votes into an
* HTML page showing possible irregularities. */
-public class MetricsWebsiteReport implements Report {
+public class MetricsWebsiteReport {
/* Date-time format to format timestamps. */
private static SimpleDateFormat dateTimeFormat;
@@ -25,30 +26,35 @@ public class MetricsWebsiteReport implements Report {
this.htmlOutputFile = new File(htmlOutputFilename);
}
- /* Process warnings. */
- public void processWarnings(SortedMap<Warning, String> warnings) {
- /* We could use these warnings instead of running all checks
- * ourselves. But we're not doing that yet. */
- }
-
/* Store the downloaded consensus and corresponding votes for later
* processing. */
- private Status downloadedConsensus;
- private SortedSet<Status> downloadedVotes;
+ private RelayNetworkStatusConsensus downloadedConsensus;
+ private SortedMap<String, RelayNetworkStatusVote> downloadedVotes =
+ new TreeMap<String, RelayNetworkStatusVote>();
public void processDownloadedConsensuses(
- SortedMap<String, Status> downloadedConsensuses) {
+ List<DescriptorRequest> downloads) {
long mostRecentValidAfterMillis = -1L;
- for (Status downloadedConsensus : downloadedConsensuses.values()) {
- if (downloadedConsensus.getValidAfterMillis() >
- mostRecentValidAfterMillis) {
- this.downloadedConsensus = downloadedConsensus;
- mostRecentValidAfterMillis =
- downloadedConsensus.getValidAfterMillis();
+ for (DescriptorRequest request : downloads) {
+ for (Descriptor descriptor : request.getDescriptors()) {
+ if (descriptor instanceof RelayNetworkStatusConsensus) {
+ RelayNetworkStatusConsensus downloadedConsensus =
+ (RelayNetworkStatusConsensus) descriptor;
+ if (downloadedConsensus.getValidAfterMillis() >
+ mostRecentValidAfterMillis) {
+ this.downloadedConsensus = downloadedConsensus;
+ mostRecentValidAfterMillis =
+ downloadedConsensus.getValidAfterMillis();
+ }
+ } else if (descriptor instanceof RelayNetworkStatusVote) {
+ RelayNetworkStatusVote vote =
+ (RelayNetworkStatusVote) descriptor;
+ this.downloadedVotes.put(vote.getNickname(), vote);
+ } else {
+ System.err.println("Did not expect a descriptor of type "
+ + descriptor.getClass() + ". Ignoring.");
+ }
}
}
- if (this.downloadedConsensus != null) {
- this.downloadedVotes = this.downloadedConsensus.getVotes();
- }
}
/* Store the DownloadStatistics reference to request download statistics
@@ -177,7 +183,7 @@ public class MetricsWebsiteReport implements Report {
if (this.downloadedVotes.size() < 1) {
this.bw.write(" <tr><td>(No votes.)</td><td></td></tr>\n");
} else {
- for (Status vote : this.downloadedVotes) {
+ for (RelayNetworkStatusVote vote : this.downloadedVotes.values()) {
this.bw.write(" <tr>\n"
+ " <td>" + vote.getNickname() + "</td>\n"
+ " <td>known-flags");
@@ -218,24 +224,36 @@ public class MetricsWebsiteReport implements Report {
this.bw.write(" <tr><td>(No votes.)</td><td></td><td></td>"
+ "</tr>\n");
} else {
- for (Status vote : this.downloadedVotes) {
+ for (RelayNetworkStatusVote vote : this.downloadedVotes.values()) {
+ int runningRelays = 0;
+ for (NetworkStatusEntry entry :
+ vote.getStatusEntries().values()) {
+ if (entry.getFlags().contains("Running")) {
+ runningRelays++;
+ }
+ }
this.bw.write(" <tr>\n"
+ " <td>" + vote.getNickname() + "</td>\n"
+ " <td>" + vote.getStatusEntries().size()
+ " total</td>\n"
- + " <td>" + vote.getRunningRelays()
- + " Running</td>\n"
+ + " <td>" + runningRelays + " Running</td>\n"
+ " </tr>\n");
}
}
+ int runningRelays = 0;
+ for (NetworkStatusEntry entry :
+ this.downloadedConsensus.getStatusEntries().values()) {
+ if (entry.getFlags().contains("Running")) {
+ runningRelays++;
+ }
+ }
this.bw.write(" <tr>\n"
+ " <td><font color=\"blue\">consensus</font>"
+ "</td>\n"
+ " <td><font color=\"blue\">"
+ this.downloadedConsensus.getStatusEntries().size()
+ " total</font></td>\n"
- + " <td><font color=\"blue\">"
- + this.downloadedConsensus.getRunningRelays()
+ + " <td><font color=\"blue\">" + runningRelays
+ " Running</font></td>\n"
+ " </tr>\n"
+ " </table>\n");
@@ -258,11 +276,10 @@ public class MetricsWebsiteReport implements Report {
if (this.downloadedVotes.size() < 1) {
this.bw.write(" <tr><td>(No votes.)</td><td></td></tr>\n");
} else {
- for (Status vote : this.downloadedVotes) {
- SortedSet<Integer> consensusMethods =
- vote.getConsensusMethods();
+ for (RelayNetworkStatusVote vote : this.downloadedVotes.values()) {
+ List<Integer> consensusMethods = vote.getConsensusMethods();
if (consensusMethods.contains(
- this.downloadedConsensus.getConsensusMethods().last())) {
+ this.downloadedConsensus.getConsensusMethod())) {
this.bw.write(" <tr>\n"
+ " <td>" + vote.getNickname() + "</td>\n"
+ " <td>consensus-methods");
@@ -289,7 +306,7 @@ public class MetricsWebsiteReport implements Report {
+ " <td><font color=\"blue\">consensus</font>"
+ "</td>\n"
+ " <td><font color=\"blue\">consensus-method "
- + this.downloadedConsensus.getConsensusMethods().last()
+ + this.downloadedConsensus.getConsensusMethod()
+ "</font></td>\n"
+ " </tr>\n"
+ " </table>\n");
@@ -311,10 +328,10 @@ public class MetricsWebsiteReport implements Report {
if (this.downloadedVotes.size() < 1) {
this.bw.write(" <tr><td>(No votes.)</td><td></td></tr>\n");
} else {
- for (Status vote : this.downloadedVotes) {
+ for (RelayNetworkStatusVote vote : this.downloadedVotes.values()) {
SortedSet<String> voteRecommendedClientVersions =
vote.getRecommendedClientVersions();
- if (voteRecommendedClientVersions != null) {
+ if (!voteRecommendedClientVersions.isEmpty()) {
if (downloadedConsensus.getRecommendedClientVersions().equals(
voteRecommendedClientVersions)) {
this.bw.write(" <tr>\n"
@@ -342,7 +359,7 @@ public class MetricsWebsiteReport implements Report {
}
SortedSet<String> voteRecommendedServerVersions =
vote.getRecommendedServerVersions();
- if (voteRecommendedServerVersions != null) {
+ if (!voteRecommendedServerVersions.isEmpty()) {
if (downloadedConsensus.getRecommendedServerVersions().equals(
voteRecommendedServerVersions)) {
this.bw.write(" <tr>\n"
@@ -415,7 +432,7 @@ public class MetricsWebsiteReport implements Report {
+ "cbtmintimeout,cbtinitialtimeout").split(",")));
Map<String, String> consensusConsensusParams =
downloadedConsensus.getConsensusParams();
- for (Status vote : this.downloadedVotes) {
+ for (RelayNetworkStatusVote vote : this.downloadedVotes.values()) {
Map<String, String> voteConsensusParams =
vote.getConsensusParams();
boolean conflictOrInvalid = false;
@@ -485,7 +502,7 @@ public class MetricsWebsiteReport implements Report {
if (this.downloadedVotes.size() < 1) {
this.bw.write(" <tr><td>(No votes.)</td><td></td></tr>\n");
} else {
- for (Status vote : this.downloadedVotes) {
+ for (RelayNetworkStatusVote vote : this.downloadedVotes.values()) {
long voteDirKeyExpiresMillis = vote.getDirKeyExpiresMillis();
if (voteDirKeyExpiresMillis - 14L * 24L * 60L * 60L * 1000L <
System.currentTimeMillis()) {
@@ -530,11 +547,17 @@ public class MetricsWebsiteReport implements Report {
if (this.downloadedVotes.size() < 1) {
this.bw.write(" <tr><td>(No votes.)</td><td></td></tr>\n");
} else {
- for (Status vote : this.downloadedVotes) {
- if (vote.getBandwidthWeights() > 0) {
+ for (RelayNetworkStatusVote vote : this.downloadedVotes.values()) {
+ int bandwidthWeights = 0;
+ for (NetworkStatusEntry entry : vote.getStatusEntries().values()) {
+ if (entry.getBandwidth().contains("Measured=")) {
+ bandwidthWeights++;
+ }
+ }
+ if (bandwidthWeights > 0) {
this.bw.write(" <tr>\n"
+ " <td>" + vote.getNickname() + "</td>\n"
- + " <td>" + vote.getBandwidthWeights()
+ + " <td>" + bandwidthWeights
+ " Measured values in w lines</td>\n"
+ " </tr>\n");
}
@@ -550,8 +573,14 @@ public class MetricsWebsiteReport implements Report {
+ " <h3><a href=\"#authorityversions\" class=\"anchor\">"
+ "Authority versions</a></h3>\n"
+ " <br>\n");
- Map<String, String> authorityVersions =
- this.downloadedConsensus.getAuthorityVersions();
+ SortedMap<String, String> authorityVersions =
+ new TreeMap<String, String>();
+ for (NetworkStatusEntry entry :
+ this.downloadedConsensus.getStatusEntries().values()) {
+ if (entry.getFlags().contains("Authority")) {
+ authorityVersions.put(entry.getNickname(), entry.getVersion());
+ }
+ }
if (authorityVersions.size() < 1) {
this.bw.write(" <p>(No relays with Authority flag found.)"
+ "</p>\n");
@@ -671,13 +700,14 @@ public class MetricsWebsiteReport implements Report {
}
this.bw.write(" </colgroup>\n");
SortedMap<String, String> allRelays = new TreeMap<String, String>();
- for (Status vote : this.downloadedVotes) {
- for (StatusEntry statusEntry : vote.getStatusEntries().values()) {
+ for (RelayNetworkStatusVote vote : this.downloadedVotes.values()) {
+ for (NetworkStatusEntry statusEntry :
+ vote.getStatusEntries().values()) {
allRelays.put(statusEntry.getFingerprint(),
statusEntry.getNickname());
}
}
- for (StatusEntry statusEntry :
+ for (NetworkStatusEntry statusEntry :
this.downloadedConsensus.getStatusEntries().values()) {
allRelays.put(statusEntry.getFingerprint(),
statusEntry.getNickname());
@@ -699,7 +729,7 @@ public class MetricsWebsiteReport implements Report {
private void writeRelayFlagsTableHeader() throws IOException {
this.bw.write(" <tr><td><br><b>Fingerprint</b></td>"
+ "<td><br><b>Nickname</b></td>\n");
- for (Status vote : this.downloadedVotes) {
+ for (RelayNetworkStatusVote vote : this.downloadedVotes.values()) {
String shortDirName = vote.getNickname().length() > 6 ?
vote.getNickname().substring(0, 5) + "." :
vote.getNickname();
@@ -714,8 +744,7 @@ public class MetricsWebsiteReport implements Report {
this.bw.write(" <tr>\n");
if (this.downloadedConsensus.containsStatusEntry(fingerprint) &&
this.downloadedConsensus.getStatusEntry(fingerprint).getFlags().
- contains("Named") &&
- !Character.isDigit(nickname.charAt(0))) {
+ contains("Named") && !Character.isDigit(nickname.charAt(0))) {
this.bw.write(" <td id=\"" + nickname
+ "\"><a href=\"relay.html?fingerprint="
+ fingerprint + "\" target=\"_blank\">"
@@ -727,18 +756,18 @@ public class MetricsWebsiteReport implements Report {
}
this.bw.write(" <td>" + nickname + "</td>\n");
SortedSet<String> relevantFlags = new TreeSet<String>();
- for (Status vote : this.downloadedVotes) {
+ for (RelayNetworkStatusVote vote : this.downloadedVotes.values()) {
if (vote.containsStatusEntry(fingerprint)) {
relevantFlags.addAll(vote.getStatusEntry(fingerprint).getFlags());
}
}
SortedSet<String> consensusFlags = null;
if (this.downloadedConsensus.containsStatusEntry(fingerprint)) {
- consensusFlags = this.downloadedConsensus.
- getStatusEntry(fingerprint).getFlags();
+ consensusFlags = this.downloadedConsensus.getStatusEntries().get(
+ fingerprint).getFlags();
relevantFlags.addAll(consensusFlags);
}
- for (Status vote : this.downloadedVotes) {
+ for (RelayNetworkStatusVote vote : this.downloadedVotes.values()) {
if (vote.containsStatusEntry(fingerprint)) {
SortedSet<String> flags = vote.getStatusEntry(fingerprint).
getFlags();
@@ -818,7 +847,7 @@ public class MetricsWebsiteReport implements Report {
+ "<td><b>In vote and consensus</b></td>"
+ "<td><b>Only in consensus</b></td>\n");
Set<String> allFingerprints = new HashSet<String>();
- for (Status vote : this.downloadedVotes) {
+ for (RelayNetworkStatusVote vote : this.downloadedVotes.values()) {
allFingerprints.addAll(vote.getStatusEntries().keySet());
}
allFingerprints.addAll(this.downloadedConsensus.getStatusEntries().
@@ -832,9 +861,9 @@ public class MetricsWebsiteReport implements Report {
for (String fingerprint : allFingerprints) {
SortedSet<String> consensusFlags =
this.downloadedConsensus.containsStatusEntry(fingerprint) ?
- this.downloadedConsensus.getStatusEntry(fingerprint).getFlags() :
- null;
- for (Status vote : this.downloadedVotes) {
+ this.downloadedConsensus.getStatusEntry(fingerprint).getFlags()
+ : null;
+ for (RelayNetworkStatusVote vote : this.downloadedVotes.values()) {
String dir = vote.getNickname();
if (vote.containsStatusEntry(fingerprint)) {
SortedSet<String> flags = vote.getStatusEntry(fingerprint).
@@ -868,7 +897,7 @@ public class MetricsWebsiteReport implements Report {
}
}
}
- for (Status vote : this.downloadedVotes) {
+ for (RelayNetworkStatusVote vote : this.downloadedVotes.values()) {
String dir = vote.getNickname();
int i = 0;
for (String flag : vote.getKnownFlags()) {
diff --git a/src/org/torproject/doctor/Parser.java b/src/org/torproject/doctor/Parser.java
deleted file mode 100755
index d318f29..0000000
--- a/src/org/torproject/doctor/Parser.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/* Copyright 2011 The Tor Project
- * See LICENSE for licensing information */
-package org.torproject.doctor;
-
-import java.io.*;
-import java.text.*;
-import java.util.*;
-import org.apache.commons.codec.binary.*;
-
-/* Parse a network status consensus or vote. */
-public class Parser {
-
- /* Parse and return a consensus and corresponding votes, or null if
- * something goes wrong. */
- public SortedMap<String, Status> parse(
- List<Download> downloadedConsensuses,
- List<Download> downloadedVotes) {
- SortedSet<Status> parsedVotes = new TreeSet<Status>();
- for (Download downloadedVote : downloadedVotes) {
- String voteString = downloadedVote.getResponseString();
- long fetchTime = downloadedVote.getFetchTime();
- Status parsedVote = this.parseConsensusOrVote(voteString, fetchTime,
- false);
- if (parsedVote != null) {
- parsedVotes.add(parsedVote);
- }
- }
- SortedMap<String, Status> parsedConsensuses =
- new TreeMap<String, Status>();
- for (Download downloadedConsensus : downloadedConsensuses) {
- String nickname = downloadedConsensus.getAuthority();
- String consensusString = downloadedConsensus.getResponseString();
- long fetchTime = downloadedConsensus.getFetchTime();
- Status parsedConsensus = this.parseConsensusOrVote(consensusString,
- fetchTime, true);
- if (parsedConsensus != null) {
- for (Status parsedVote : parsedVotes) {
- if (parsedConsensus.getValidAfterMillis() ==
- parsedVote.getValidAfterMillis()) {
- parsedConsensus.addVote(parsedVote);
- }
- }
- parsedConsensuses.put(nickname, parsedConsensus);
- }
- }
- return parsedConsensuses;
- }
-
- /* Date-time formats to parse and format timestamps. */
- private static SimpleDateFormat dateTimeFormat;
- static {
- dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
- }
-
- /* Parse a consensus or vote string into a Status instance. */
- private Status parseConsensusOrVote(String statusString, long fetchTime,
- boolean isConsensus) {
- if (statusString == null) {
- return null;
- }
- Status status = new Status();
- status.setUnparsedString(statusString);
- status.setFetchTime(fetchTime);
- try {
- BufferedReader br = new BufferedReader(new StringReader(
- statusString));
- String line, rLine = null, sLine = null;
- int totalRelays = 0, runningRelays = 0, bandwidthWeights = 0;
- while ((line = br.readLine()) != null) {
- if (line.startsWith("consensus-method ") ||
- line.startsWith("consensus-methods ")) {
- SortedSet<Integer> consensusMethods = new TreeSet<Integer>();
- String[] parts = line.split(" ");
- for (int i = 1; i < parts.length; i++) {
- consensusMethods.add(Integer.parseInt(parts[i]));
- }
- status.setConsensusMethods(consensusMethods);
- } else if (line.startsWith("valid-after ")) {
- try {
- status.setValidAfterMillis(dateTimeFormat.parse(
- line.substring("valid-after ".length())).getTime());
- } catch (ParseException e) {
- System.err.println("Could not parse valid-after timestamp in "
- + "line '" + line + "' of a "
- + (isConsensus ? "consensus" : "vote") + ". Skipping.");
- return null;
- }
- } else if (line.startsWith("client-versions ")) {
- status.setRecommendedClientVersions(
- new TreeSet<String>(Arrays.asList(
- line.split(" ")[1].split(","))));
- } else if (line.startsWith("server-versions ")) {
- status.setRecommendedServerVersions(
- new TreeSet<String>(Arrays.asList(
- line.split(" ")[1].split(","))));
- } else if (line.startsWith("known-flags ")) {
- for (String flag : line.substring("known-flags ".length()).
- split(" ")) {
- status.addKnownFlag(flag);
- }
- } else if (line.startsWith("params ")) {
- if (line.length() > "params ".length()) {
- for (String param :
- line.substring("params ".length()).split(" ")) {
- String paramName = param.split("=")[0];
- String paramValue = param.split("=")[1];
- status.addConsensusParam(paramName, paramValue);
- }
- }
- } else if (line.startsWith("dir-source ")) {
- String nickname = line.split(" ")[1];
- String fingerprint = line.split(" ")[2];
- if (isConsensus) {
- status.addContainedVote(fingerprint);
- } else {
- status.setNickname(line.split(" ")[1]);
- status.setFingerprint(line.split(" ")[2]);
- }
- } else if (line.startsWith("dir-key-expires ")) {
- try {
- status.setDirKeyExpiresMillis(dateTimeFormat.parse(
- line.substring("dir-key-expires ".length())).getTime());
- } catch (ParseException e) {
- System.err.println("Could not parse dir-key-expires "
- + "timestamp in line '" + line + "' of a "
- + (isConsensus ? "consensus" : "vote") + ". Skipping.");
- return null;
- }
- } else if (line.startsWith("r ") ||
- line.equals("directory-footer")) {
- if (rLine != null) {
- StatusEntry statusEntry = new StatusEntry();
- statusEntry.setNickname(rLine.split(" ")[1]);
- statusEntry.setFingerprint(Hex.encodeHexString(
- Base64.decodeBase64(rLine.split(" ")[2] + "=")).
- toUpperCase());
- SortedSet<String> flags = new TreeSet<String>();
- if (sLine.length() > 2) {
- for (String flag : sLine.substring(2).split(" ")) {
- flags.add(flag);
- }
- }
- statusEntry.setFlags(flags);
- status.addStatusEntry(statusEntry);
- }
- if (line.startsWith("r ")) {
- rLine = line;
- }
- } else if (line.startsWith("s ") || line.equals("s")) {
- sLine = line;
- if (line.contains(" Running")) {
- runningRelays++;
- }
- } else if (line.startsWith("v ") &&
- sLine.contains(" Authority")) {
- String nickname = rLine.split(" ")[1];
- String versionString = line.substring(2);
- status.addAuthorityVersion(nickname, versionString);
- } else if (line.startsWith("w ") && !isConsensus &&
- line.contains(" Measured")) {
- bandwidthWeights++;
- } else if (line.startsWith("directory-signature ") &&
- isConsensus) {
- String fingerprint = line.split(" ")[1];
- status.addContainedSignature(fingerprint);
- }
- }
- br.close();
- status.setRunningRelays(runningRelays);
- status.setBandwidthWeights(bandwidthWeights);
- } catch (IOException e) {
- System.err.println("Caught an IOException while parsing a "
- + (isConsensus ? "consensus" : "vote") + " string. Skipping.");
- return null;
- }
- return status;
- }
-}
-
diff --git a/src/org/torproject/doctor/Report.java b/src/org/torproject/doctor/Report.java
deleted file mode 100755
index 2e508bc..0000000
--- a/src/org/torproject/doctor/Report.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Copyright 2011 The Tor Project
- * See LICENSE for licensing information */
-package org.torproject.doctor;
-
-import java.util.*;
-
-/* Transform findings from parsing consensuses and votes into a report of
- * some form. */
-public interface Report {
-
- /* Process the downloaded current consensus and corresponding votes to
- * find irregularities between them. */
- public abstract void processDownloadedConsensuses(
- SortedMap<String, Status> downloadedConsensuses);
-
- /* Process warnings consisting of warning type and details. */
- public abstract void processWarnings(
- SortedMap<Warning, String> warnings);
-
- /* Include download statistics. */
- public abstract void includeFetchStatistics(
- DownloadStatistics statistics);
-
- /* Finish writing report. */
- public abstract void writeReport();
-}
-
diff --git a/src/org/torproject/doctor/Status.java b/src/org/torproject/doctor/Status.java
deleted file mode 100755
index df41e47..0000000
--- a/src/org/torproject/doctor/Status.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/* Copyright 2011 The Tor Project
- * See LICENSE for licensing information */
-package org.torproject.doctor;
-
-import java.util.*;
-
-/* Contains the unparsed string and parsed fields from a network status
- * consensus or vote. */
-public class Status implements Comparable<Status> {
-
- /* Helper methods to implement the Comparable interface; Status
- * instances are compared by nickname of the publishing directory
- * authorities. */
- public int compareTo(Status o) {
- return this.nickname.compareTo(o.nickname);
- }
- public boolean equals(Object o) {
- return (o instanceof Status &&
- this.nickname.equals(((Status) o).nickname));
- }
-
- /* Unparsed string that was downloaded or read from disk and that can
- * be written to disk. */
- private String unparsedString;
- public void setUnparsedString(String unparsedString) {
- this.unparsedString = unparsedString;
- }
- public String getUnparsedString() {
- return this.unparsedString;
- }
-
- /* Fetch time in millis. */
- private long fetchTime;
- public void setFetchTime(long fetchTime) {
- this.fetchTime = fetchTime;
- }
- public long getFetchTime() {
- return this.fetchTime;
- }
-
- /* Votes published at the same time as this consensus; votes don't
- * reference any statuses. */
- private SortedSet<Status> votes = new TreeSet<Status>();
- public void addVote(Status vote) {
- this.votes.add(vote);
- }
- public SortedSet<Status> getVotes() {
- return this.votes;
- }
-
- /* Fingerprint of the directory authority publishing this vote; left
- * empty for consensuses. */
- private String fingerprint;
- public void setFingerprint(String fingerprint) {
- this.fingerprint = fingerprint;
- }
- public String getFingerprint() {
- return this.fingerprint;
- }
-
- /* Nickname of the directory authority publishing this vote; left empty
- * for consensuses. */
- private String nickname;
- public void setNickname(String nickname) {
- this.nickname= nickname;
- }
- public String getNickname() {
- return this.nickname;
- }
-
- /* Valid-after time in milliseconds. */
- private long validAfterMillis;
- public void setValidAfterMillis(long validAfterMillis) {
- this.validAfterMillis = validAfterMillis;
- }
- public long getValidAfterMillis() {
- return this.validAfterMillis;
- }
-
- /* Consensus parameters. */
- private SortedMap<String, String> consensusParams =
- new TreeMap<String, String>();
- public void addConsensusParam(String paramName, String paramValue) {
- this.consensusParams.put(paramName, paramValue);
- }
- public SortedMap<String, String> getConsensusParams() {
- return this.consensusParams;
- }
-
- /* Consensus methods supported by the directory authority sending a vote
- * or of the produced consensus. */
- private SortedSet<Integer> consensusMethods;
- public void setConsensusMethods(SortedSet<Integer> consensusMethods) {
- this.consensusMethods = consensusMethods;
- }
- public SortedSet<Integer> getConsensusMethods() {
- return this.consensusMethods;
- }
-
- /* Recommended server versions. */
- private SortedSet<String> recommendedServerVersions;
- public void setRecommendedServerVersions(
- SortedSet<String> recommendedServerVersions) {
- this.recommendedServerVersions = recommendedServerVersions;
- }
- public SortedSet<String> getRecommendedServerVersions() {
- return this.recommendedServerVersions;
- }
-
- /* Recommended client versions. */
- private SortedSet<String> recommendedClientVersions;
- public void setRecommendedClientVersions(
- SortedSet<String> recommendedClientVersions) {
- this.recommendedClientVersions = recommendedClientVersions;
- }
- public SortedSet<String> getRecommendedClientVersions() {
- return this.recommendedClientVersions;
- }
-
- /* Expiration times of directory signing keys. */
- private long dirKeyExpiresMillis;
- public void setDirKeyExpiresMillis(long dirKeyExpiresMillis) {
- this.dirKeyExpiresMillis = dirKeyExpiresMillis;
- }
- public long getDirKeyExpiresMillis() {
- return this.dirKeyExpiresMillis;
- }
-
- /* Known flags by the directory authority sending a vote or of the
- * produced consensus. */
- private SortedSet<String> knownFlags = new TreeSet<String>();
- public void addKnownFlag(String knownFlag) {
- this.knownFlags.add(knownFlag);
- }
- public SortedSet<String> getKnownFlags() {
- return this.knownFlags;
- }
-
- /* Fingerprints of directory authorities of contained votes (only
- * relevant for consensuses). */
- private SortedSet<String> containedVotes = new TreeSet<String>();
- public void addContainedVote(String fingerprint) {
- this.containedVotes.add(fingerprint);
- }
- public SortedSet<String> getContainedVotes() {
- return this.containedVotes;
- }
-
- /* Fingerprints of directory authorities of contained signatures (only
- * relevant for consensuses). */
- private SortedSet<String> containedSignatures = new TreeSet<String>();
- public void addContainedSignature(String fingerprint) {
- this.containedSignatures.add(fingerprint);
- }
- public SortedSet<String> getContainedSignatures() {
- return this.containedSignatures;
- }
-
- /* Number of status entries with the Running flag. */
- private int runningRelays;
- public void setRunningRelays(int runningRelays) {
- this.runningRelays = runningRelays;
- }
- public int getRunningRelays() {
- return this.runningRelays;
- }
-
- /* Number of status entries containing bandwidth weights (only relevant
- * in votes). */
- private int bandwidthWeights;
- public void setBandwidthWeights(int bandwidthWeights) {
- this.bandwidthWeights = bandwidthWeights;
- }
- public int getBandwidthWeights() {
- return this.bandwidthWeights;
- }
-
- /* Status entries contained in this status. */
- private SortedMap<String, StatusEntry> statusEntries =
- new TreeMap<String, StatusEntry>();
- public void addStatusEntry(StatusEntry statusEntry) {
- this.statusEntries.put(statusEntry.getFingerprint(), statusEntry);
- }
- public SortedMap<String, StatusEntry> getStatusEntries() {
- return this.statusEntries;
- }
- public boolean containsStatusEntry(String fingerprint) {
- return this.statusEntries.containsKey(fingerprint);
- }
- public StatusEntry getStatusEntry(String fingerprint) {
- return this.statusEntries.get(fingerprint);
- }
-
- /* Versions of directory authorities (only set in a consensus). */
- private SortedMap<String, String> authorityVersions =
- new TreeMap<String, String>();
- public void addAuthorityVersion(String fingerprint,
- String versionString) {
- this.authorityVersions.put(fingerprint, versionString);
- }
- public SortedMap<String, String> getAuthorityVersions() {
- return this.authorityVersions;
- }
-}
-
diff --git a/src/org/torproject/doctor/StatusEntry.java b/src/org/torproject/doctor/StatusEntry.java
deleted file mode 100755
index 18f1149..0000000
--- a/src/org/torproject/doctor/StatusEntry.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/* Copyright 2011 The Tor Project
- * See LICENSE for licensing information */
-package org.torproject.doctor;
-
-import java.util.*;
-
-/* Contains the parsed data from a network status entry contained in a
- * network status consensus or vote. */
-public class StatusEntry implements Comparable<StatusEntry> {
-
- /* Helper methods to implement the Comparable interface; StatusEntry
- * instances are compared by fingerprint. */
- public int compareTo(StatusEntry o) {
- return this.fingerprint.compareTo(o.fingerprint);
- }
- public boolean equals(Object o) {
- return (o instanceof StatusEntry &&
- this.fingerprint.equals(((StatusEntry) o).fingerprint));
- }
-
- /* Relay fingerprint. */
- private String fingerprint;
- public void setFingerprint(String fingerprint) {
- this.fingerprint = fingerprint;
- }
- public String getFingerprint() {
- return this.fingerprint;
- }
-
- /* Relay nickname. */
- private String nickname;
- public void setNickname(String nickname) {
- this.nickname = nickname;
- }
- public String getNickname() {
- return this.nickname;
- }
-
- /* Relay flags. */
- private SortedSet<String> flags;
- public void setFlags(SortedSet<String> flags) {
- this.flags = flags;
- }
- public SortedSet<String> getFlags() {
- return this.flags;
- }
-}
-
diff --git a/src/org/torproject/doctor/StatusFileReport.java b/src/org/torproject/doctor/StatusFileReport.java
index 884dc18..7890005 100755
--- a/src/org/torproject/doctor/StatusFileReport.java
+++ b/src/org/torproject/doctor/StatusFileReport.java
@@ -8,7 +8,7 @@ import java.util.*;
/* Check a given consensus and votes for irregularities and write results
* to stdout while rate-limiting warnings based on severity. */
-public class StatusFileReport implements Report {
+public class StatusFileReport {
/* Date-time format to format timestamps. */
private static SimpleDateFormat dateTimeFormat;
@@ -17,27 +17,12 @@ public class StatusFileReport implements Report {
dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
}
- /* Downloaded consensus and corresponding votes for later
- * processing. */
- private SortedMap<String, Status> downloadedConsensuses;
- private Status downloadedConsensus;
- private SortedSet<Status> downloadedVotes;
- public void processDownloadedConsensuses(
- SortedMap<String, Status> downloadedConsensuses) {
- this.downloadedConsensuses = downloadedConsensuses;
- }
-
/* Warnings obtained from checking the current consensus and votes. */
private SortedMap<Warning, String> warnings;
public void processWarnings(SortedMap<Warning, String> warnings) {
this.warnings = warnings;
}
- /* Ignore download statistics for this report. */
- public void includeFetchStatistics(DownloadStatistics statistics) {
- /* Do nothing. */
- }
-
/* Check consensuses and votes for irregularities and write output to
* stdout. */
public void writeReport() {
1
0
[metrics-lib/master] Add a work-in-progress note to the README.
by karsten@torproject.org 13 Dec '11
by karsten@torproject.org 13 Dec '11
13 Dec '11
commit 34f4820ac3504c00ab5c09e85376a49fac47031c
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Mon Dec 12 19:15:24 2011 +0100
Add a work-in-progress note to the README.
---
README | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/README b/README
index 9f235d3..f192501 100755
--- a/README
+++ b/README
@@ -24,3 +24,13 @@ running, batch-processing applications and not for continuously running
applications that rely on learning about changes to an underlying
descriptor source.
+Work-In-Progress Notice
+=======================
+
+As of December 2011, this library is a work in progress. Its interfaces
+may change at any time. If you want to be informed of interface changes
+during the initial development phase, ask for your software to be added to
+the list below (software name, repository, contact person):
+
+ - DocTor, https://git.torproject.org/doctor.git, karsten
+
1
0
[metrics-lib/master] Implement parsing of network status votes.
by karsten@torproject.org 13 Dec '11
by karsten@torproject.org 13 Dec '11
13 Dec '11
commit 276e0ef72aae65f0e69cb55bb4b1d80c537691e9
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Tue Dec 13 10:17:34 2011 +0100
Implement parsing of network status votes.
---
.../descriptor/RelayNetworkStatusConsensus.java | 7 +
.../descriptor/RelayNetworkStatusVote.java | 80 +++++-
.../descriptor/impl/NetworkStatusEntryImpl.java | 7 +-
.../impl/RelayNetworkStatusConsensusImpl.java | 6 +
.../impl/RelayNetworkStatusVoteImpl.java | 315 +++++++++++++++++++-
5 files changed, 408 insertions(+), 7 deletions(-)
diff --git a/src/org/torproject/descriptor/RelayNetworkStatusConsensus.java b/src/org/torproject/descriptor/RelayNetworkStatusConsensus.java
index 192c963..452a0ba 100755
--- a/src/org/torproject/descriptor/RelayNetworkStatusConsensus.java
+++ b/src/org/torproject/descriptor/RelayNetworkStatusConsensus.java
@@ -46,6 +46,13 @@ public interface RelayNetworkStatusConsensus extends Descriptor {
/* Return status entries, one for each contained relay. */
public SortedMap<String, NetworkStatusEntry> getStatusEntries();
+ /* Return whether a status entry with the given fingerprint exists. */
+ public boolean containsStatusEntry(String fingerprint);
+
+ /* Return a status entry by fingerprint or null if no such status entry
+ * exists. */
+ public NetworkStatusEntry getStatusEntry(String fingerprint);
+
/* Return directory signatures. */
public SortedMap<String, String> getDirectorySignatures();
diff --git a/src/org/torproject/descriptor/RelayNetworkStatusVote.java b/src/org/torproject/descriptor/RelayNetworkStatusVote.java
index 62d1307..7d85a0c 100755
--- a/src/org/torproject/descriptor/RelayNetworkStatusVote.java
+++ b/src/org/torproject/descriptor/RelayNetworkStatusVote.java
@@ -2,11 +2,87 @@
* See LICENSE for licensing information */
package org.torproject.descriptor;
+import java.util.List;
import java.util.SortedMap;
import java.util.SortedSet;
-/* Contains the unparsed string and parsed fields from a network status
- * vote. */
+/* Contains a network status vote. */
public interface RelayNetworkStatusVote extends Descriptor {
+
+ /* Return the network status version. */
+ public int getNetworkStatusVersion();
+
+ /* Return the consensus method. */
+ public List<Integer> getConsensusMethods();
+
+ /* Return the publication time in milliseconds. */
+ public long getPublishedMillis();
+
+ /* Return the valid-after time in milliseconds. */
+ public long getValidAfterMillis();
+
+ /* Return the fresh-until time in milliseconds. */
+ public long getFreshUntilMillis();
+
+ /* Return the valid-until time in milliseconds. */
+ public long getValidUntilMillis();
+
+ /* Return a list of the voting-delay times in seconds. */
+ public List<Long> getVotingDelay();
+
+ /* Return cecommended server versions. */
+ public SortedSet<String> getRecommendedServerVersions();
+
+ /* Return recommended client versions. */
+ public SortedSet<String> getRecommendedClientVersions();
+
+ /* Return known relay flags. */
+ public SortedSet<String> getKnownFlags();
+
+ /* Return consensus parameters. */
+ public SortedMap<String, String> getConsensusParams();
+
+ /* Return the directory nickname. */
+ public String getNickname();
+
+ /* Return the directory identity. */
+ public String getIdentity();
+
+ /* Return the IP address. */
+ public String getAddress();
+
+ /* Return the DiRPort. */
+ public int getDirport();
+
+ /* Return the ORPort. */
+ public int getOrport();
+
+ /* Return the contact line. */
+ public String getContactLine();
+
+ /* Return the directory key certificate version. */
+ public int getDirKeyCertificateVersion();
+
+ /* Return the directory key publication timestamp. */
+ public long getDirKeyPublishedMillis();
+
+ /* Return the directory key expiration timestamp. */
+ public long getDirKeyExpiresMillis();
+
+ /* Return the signing key digest. */
+ public String getSigningKeyDigest();
+
+ /* Return status entries, one for each contained relay. */
+ public SortedMap<String, NetworkStatusEntry> getStatusEntries();
+
+ /* Return whether a status entry with the given fingerprint exists. */
+ public boolean containsStatusEntry(String fingerprint);
+
+ /* Return a status entry by fingerprint or null if no such status entry
+ * exists. */
+ public NetworkStatusEntry getStatusEntry(String fingerprint);
+
+ /* Return directory signatures. */
+ public SortedMap<String, String> getDirectorySignatures();
}
diff --git a/src/org/torproject/descriptor/impl/NetworkStatusEntryImpl.java b/src/org/torproject/descriptor/impl/NetworkStatusEntryImpl.java
index d0a511d..610fb1a 100755
--- a/src/org/torproject/descriptor/impl/NetworkStatusEntryImpl.java
+++ b/src/org/torproject/descriptor/impl/NetworkStatusEntryImpl.java
@@ -57,12 +57,15 @@ public class NetworkStatusEntryImpl implements NetworkStatusEntry {
} else if (line.startsWith("s ")) {
this.flags.addAll(Arrays.asList(line.substring("s ".length()).
split(" ")));
- } else if (line.startsWith("v ")) {
- this.version = line.substring("v ".length());
+ } else if (line.startsWith("v ") || line.startsWith("opt v")) {
+ this.version = line.substring(
+ line.startsWith("v ") ? "v ".length() : "opt v".length());
} else if (line.startsWith("w ")) {
this.bandwidth = line.substring("w ".length());
} else if (line.startsWith("p ")) {
this.ports = line.substring(2);
+ } else if (line.startsWith("m ")) {
+ /* TODO Parse m lines in votes. */
} else {
throw new RuntimeException("Unknown line '" + line + "' in "
+ "status entry.");
diff --git a/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java b/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java
index a9579a6..3d2b0a2 100755
--- a/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java
+++ b/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java
@@ -291,6 +291,12 @@ public class RelayNetworkStatusConsensusImpl
public SortedMap<String, NetworkStatusEntry> getStatusEntries() {
return new TreeMap<String, NetworkStatusEntry>(this.statusEntries);
}
+ public boolean containsStatusEntry(String fingerprint) {
+ return this.statusEntries.containsKey(fingerprint);
+ }
+ public NetworkStatusEntry getStatusEntry(String fingerprint) {
+ return this.statusEntries.get(fingerprint);
+ }
private SortedMap<String, String> directorySignatures =
new TreeMap<String, String>();
diff --git a/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java b/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
index 84a81e2..fa5b4d5 100755
--- a/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
+++ b/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
@@ -2,14 +2,26 @@
* See LICENSE for licensing information */
package org.torproject.descriptor.impl;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TimeZone;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import org.torproject.descriptor.Descriptor;
+import org.torproject.descriptor.NetworkStatusEntry;
import org.torproject.descriptor.RelayNetworkStatusVote;
/* Contains a network status vote. */
-/* TODO This class doesn't contain any parsing code yet, and it would be
- * sharing a lot of that code with the consensus class. Should there be
- * an abstract super class for the two? */
+/* TODO This class is sharing a lot of parsing code with the consensus
+ * class. Should there be an abstract super class for the two? */
public class RelayNetworkStatusVoteImpl
implements RelayNetworkStatusVote {
@@ -40,11 +52,308 @@ public class RelayNetworkStatusVoteImpl
protected RelayNetworkStatusVoteImpl(byte[] voteBytes) {
this.voteBytes = voteBytes;
+ this.parseVoteBytes();
+ this.checkConsistency();
+ /* TODO Find a way to handle parse and consistency-check problems. */
+ }
+
+ private void parseVoteBytes() {
+ String line = null;
+ try {
+ BufferedReader br = new BufferedReader(new StringReader(
+ new String(this.voteBytes)));
+ SimpleDateFormat dateTimeFormat = new SimpleDateFormat(
+ "yyyy-MM-dd HH:mm:ss");
+ dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ StringBuilder dirSourceEntryLines = null, statusEntryLines = null;
+ boolean skipCrypto = false;
+ while ((line = br.readLine()) != null) {
+ if (line.startsWith("network-status-version ")) {
+ this.networkStatusVersion = Integer.parseInt(line.substring(
+ "network-status-version ".length()));
+ } else if (line.startsWith("vote-status ")) {
+ if (!line.equals("vote-status vote")) {
+ throw new RuntimeException("Line '" + line + "' indicates "
+ + "that this string is not a vote. Aborting parsing.");
+ }
+ } else if (line.startsWith("consensus-methods ")) {
+ for (String consensusMethodString : line.substring(
+ "consensus-methods ".length()).split(" ")) {
+ this.consensusMethods.add(Integer.parseInt(
+ consensusMethodString));
+ }
+ } else if (line.startsWith("published ")) {
+ this.publishedMillis = dateTimeFormat.parse(
+ line.substring("published ".length())).getTime();
+ } else if (line.startsWith("valid-after ")) {
+ this.validAfterMillis = dateTimeFormat.parse(
+ line.substring("valid-after ".length())).getTime();
+ } else if (line.startsWith("fresh-until ")) {
+ this.freshUntilMillis = dateTimeFormat.parse(
+ line.substring("fresh-until ".length())).getTime();
+ } else if (line.startsWith("valid-until ")) {
+ this.validUntilMillis = dateTimeFormat.parse(
+ line.substring("valid-until ".length())).getTime();
+ } else if (line.startsWith("voting-delay ")) {
+ for (String votingDelayString : line.substring(
+ "voting-delay ".length()).split(" ")) {
+ this.votingDelay.add(Long.parseLong(votingDelayString));
+ }
+ } else if (line.startsWith("client-versions ")) {
+ this.recommendedClientVersions.addAll(
+ Arrays.asList(line.split(" ")[1].split(",")));
+ } else if (line.startsWith("server-versions ")) {
+ this.recommendedServerVersions.addAll(
+ Arrays.asList(line.split(" ")[1].split(",")));
+ } else if (line.startsWith("known-flags ")) {
+ for (String flag : line.substring("known-flags ".length()).
+ split(" ")) {
+ this.knownFlags.add(flag);
+ }
+ } else if (line.startsWith("params ")) {
+ if (line.length() > "params ".length()) {
+ for (String param :
+ line.substring("params ".length()).split(" ")) {
+ String paramName = param.split("=")[0];
+ String paramValue = param.split("=")[1];
+ this.consensusParams.put(paramName, paramValue);
+ }
+ }
+ } else if (line.startsWith("dir-source ")) {
+ String[] parts = line.split(" ");
+ this.nickname = parts[1];
+ this.identity = parts[2];
+ this.address = parts[4];
+ this.dirPort = Integer.parseInt(parts[5]);
+ this.orPort = Integer.parseInt(parts[6]);
+ /* TODO Add code for parsing legacy dir sources. */
+ } else if (line.startsWith("contact ")) {
+ this.contactLine = line.substring("contact ".length());
+ } else if (line.startsWith("dir-key-certificate-version ")) {
+ this.dirKeyCertificateVersion = Integer.parseInt(line.substring(
+ "dir-key-certificate-version ".length()));
+ } else if (line.startsWith("fingerprint ")) {
+ /* Nothing new to learn here. We already know the fingerprint
+ * from the dir-source line. */
+ } else if (line.startsWith("dir-key-published ")) {
+ this.dirKeyPublishedMillis = dateTimeFormat.parse(
+ line.substring("dir-key-published ".length())).getTime();
+ } else if (line.startsWith("dir-key-expires ")) {
+ this.dirKeyExpiresMillis = dateTimeFormat.parse(
+ line.substring("dir-key-expires ".length())).getTime();
+ } else if (line.equals("dir-identity-key") ||
+ line.equals("dir-signing-key") ||
+ line.equals("dir-key-crosscert") ||
+ line.equals("dir-key-certification")) {
+ /* Ignore crypto parts for now. */
+ } else if (line.startsWith("r ") ||
+ line.equals("directory-footer")) {
+ if (statusEntryLines != null) {
+ NetworkStatusEntryImpl statusEntry =
+ new NetworkStatusEntryImpl(
+ statusEntryLines.toString().getBytes());
+ this.statusEntries.put(statusEntry.getFingerprint(),
+ statusEntry);
+ statusEntryLines = null;
+ }
+ if (line.startsWith("r ")) {
+ statusEntryLines = new StringBuilder();
+ statusEntryLines.append(line + "\n");
+ }
+ } else if (line.startsWith("s ") || line.equals("s") ||
+ line.startsWith("opt v ") || line.startsWith("w ") ||
+ line.startsWith("p ") || line.startsWith("m ")) {
+ statusEntryLines.append(line + "\n");
+ } else if (line.startsWith("directory-signature ")) {
+ String[] parts = line.split(" ");
+ String identity = parts[1];
+ String signingKeyDigest = parts[2];
+ this.directorySignatures.put(identity, signingKeyDigest);
+ } else if (line.startsWith("-----BEGIN")) {
+ skipCrypto = true;
+ } else if (line.startsWith("-----END")) {
+ skipCrypto = false;
+ } else if (!skipCrypto) {
+ throw new RuntimeException("Unrecognized line '" + line + "'.");
+ }
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Internal error: Ran into an "
+ + "IOException while parsing a String in memory. Something's "
+ + "really wrong.", e);
+ } catch (ParseException e) {
+ /* TODO Handle me correctly. */
+ throw new RuntimeException("Parse error in line '" + line + "'.");
+ } catch (NumberFormatException e) {
+ /* TODO Handle me. In theory, we shouldn't catch runtime
+ * exceptions, but in this case it keeps the parsing code small. */
+ } catch (ArrayIndexOutOfBoundsException e) {
+ /* TODO Handle me. In theory, we shouldn't catch runtime
+ * exceptions, but in this case it keeps the parsing code small. */
+ }
}
private byte[] voteBytes;
public byte[] getRawDescriptorBytes() {
return this.voteBytes;
}
+
+ private int networkStatusVersion;
+ public int getNetworkStatusVersion() {
+ return this.networkStatusVersion;
+ }
+
+ private List<Integer> consensusMethods = new ArrayList<Integer>();
+ public List<Integer> getConsensusMethods() {
+ return this.consensusMethods;
+ }
+
+ private long publishedMillis;
+ public long getPublishedMillis() {
+ return this.publishedMillis;
+ }
+
+ private long validAfterMillis;
+ public long getValidAfterMillis() {
+ return this.validAfterMillis;
+ }
+
+ private long freshUntilMillis;
+ public long getFreshUntilMillis() {
+ return this.freshUntilMillis;
+ }
+
+ private long validUntilMillis;
+ public long getValidUntilMillis() {
+ return this.validUntilMillis;
+ }
+
+ private List<Long> votingDelay = new ArrayList<Long>();
+ public List<Long> getVotingDelay() {
+ return new ArrayList<Long>(this.votingDelay);
+ }
+
+ private SortedSet<String> recommendedClientVersions =
+ new TreeSet<String>();
+ public SortedSet<String> getRecommendedClientVersions() {
+ return new TreeSet<String>(this.recommendedClientVersions);
+ }
+
+ private SortedSet<String> recommendedServerVersions =
+ new TreeSet<String>();
+ public SortedSet<String> getRecommendedServerVersions() {
+ return new TreeSet<String>(this.recommendedServerVersions);
+ }
+
+ private SortedSet<String> knownFlags = new TreeSet<String>();
+ public SortedSet<String> getKnownFlags() {
+ return new TreeSet<String>(this.knownFlags);
+ }
+
+ private SortedMap<String, String> consensusParams =
+ new TreeMap<String, String>();
+ public SortedMap<String, String> getConsensusParams() {
+ return new TreeMap<String, String>(this.consensusParams);
+ }
+
+ private String nickname;
+ public String getNickname() {
+ return this.nickname;
+ }
+
+ private String identity;
+ public String getIdentity() {
+ return this.identity;
+ }
+
+ private String address;
+ public String getAddress() {
+ return this.address;
+ }
+
+ private int dirPort;
+ public int getDirport() {
+ return this.dirPort;
+ }
+
+ private int orPort;
+ public int getOrport() {
+ return this.orPort;
+ }
+
+ private String contactLine;
+ public String getContactLine() {
+ return this.contactLine;
+ }
+
+ private int dirKeyCertificateVersion;
+ public int getDirKeyCertificateVersion() {
+ return this.dirKeyCertificateVersion;
+ }
+
+ private long dirKeyPublishedMillis;
+ public long getDirKeyPublishedMillis() {
+ return this.dirKeyPublishedMillis;
+ }
+
+ private long dirKeyExpiresMillis;
+ public long getDirKeyExpiresMillis() {
+ return this.dirKeyExpiresMillis;
+ }
+
+ private String signingKeyDigest;
+ public String getSigningKeyDigest() {
+ return this.signingKeyDigest;
+ }
+
+ private SortedMap<String, NetworkStatusEntry> statusEntries =
+ new TreeMap<String, NetworkStatusEntry>();
+ public SortedMap<String, NetworkStatusEntry> getStatusEntries() {
+ return new TreeMap<String, NetworkStatusEntry>(this.statusEntries);
+ }
+ public boolean containsStatusEntry(String fingerprint) {
+ return this.statusEntries.containsKey(fingerprint);
+ }
+ public NetworkStatusEntry getStatusEntry(String fingerprint) {
+ return this.statusEntries.get(fingerprint);
+ }
+
+
+ private SortedMap<String, String> directorySignatures =
+ new TreeMap<String, String>();
+ public SortedMap<String, String> getDirectorySignatures() {
+ return new TreeMap<String, String>(this.directorySignatures);
+ }
+
+ private void checkConsistency() {
+ if (this.networkStatusVersion == 0) {
+ throw new RuntimeException("Consensus doesn't contain a "
+ + "'network-status-version' line.");
+ }
+ if (this.validAfterMillis == 0L) {
+ throw new RuntimeException("Consensus doesn't contain a "
+ + "'valid-after' line.");
+ }
+ if (this.freshUntilMillis == 0L) {
+ throw new RuntimeException("Consensus doesn't contain a "
+ + "'fresh-until' line.");
+ }
+ if (this.validUntilMillis == 0L) {
+ throw new RuntimeException("Consensus doesn't contain a "
+ + "'valid-until' line.");
+ }
+ if (this.votingDelay.isEmpty()) {
+ throw new RuntimeException("Consensus doesn't contain a "
+ + "'voting-delay' line.");
+ }
+ if (this.knownFlags.isEmpty()) {
+ throw new RuntimeException("Consensus doesn't contain a "
+ + "'known-flags' line.");
+ }
+ if (this.statusEntries.isEmpty()) {
+ throw new RuntimeException("Consensus doesn't contain any 'r' "
+ + "lines.");
+ }
+ }
}
1
0
12 Dec '11
Author: phobos
Date: 2011-12-12 21:09:13 +0000 (Mon, 12 Dec 2011)
New Revision: 25250
Added:
projects/presentations/slides-pi11.odp
projects/presentations/slides-pi11.pdf
Log:
add roger's latest presentations.
Added: projects/presentations/slides-pi11.odp
===================================================================
(Binary files differ)
Property changes on: projects/presentations/slides-pi11.odp
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: projects/presentations/slides-pi11.pdf
===================================================================
(Binary files differ)
Property changes on: projects/presentations/slides-pi11.pdf
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
1
0
12 Dec '11
commit d688a40a0e7c1e8417ecdc463821e50cd1762715
Author: Robert Ransom <rransom.8774(a)gmail.com>
Date: Mon Dec 12 11:25:55 2011 -0800
Don't crash on startup of a dormant relay
If a relay is dormant at startup, it will call init_keys before
crypto_set_tls_dh_prime. This is bad. Let's make it not so bad, because
someday it *will* happen again.
---
changes/bug4702 | 6 ++++++
src/common/crypto.c | 7 +++++--
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/changes/bug4702 b/changes/bug4702
new file mode 100644
index 0000000..dcd3bfc
--- /dev/null
+++ b/changes/bug4702
@@ -0,0 +1,6 @@
+ o Minor bugfixes:
+
+ - Fix an assertion failure when a relay with accounting enabled
+ starts up while dormant. Fixes bug 4702; bugfix on
+ 0.2.3.9-alpha.
+
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 2aa3fc9..673fc0c 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -2089,8 +2089,11 @@ init_dh_param(void)
dh_param_p = circuit_dh_prime;
dh_param_g = generator;
- /* Should be already set by config.c. */
- tor_assert(dh_param_p_tls);
+ /* Ensure that we have TLS DH parameters set up, too, even if we're
+ going to change them soon. */
+ if (!dh_param_p_tls) {
+ crypto_set_tls_dh_prime(NULL);
+ }
}
/** Number of bits to use when choosing the x or y value in a Diffie-Hellman
1
0
commit 48633568861ce099c098c632bf224ffd5bfadd69
Author: George Kadianakis <desnacked(a)gmail.com>
Date: Sun Dec 11 03:26:53 2011 +0100
Add support for doxygen.
---
.gitignore | 2 +
Doxyfile | 1418 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Makefile.am | 3 +
3 files changed, 1423 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
index a58a8c5..848c2b5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,3 +26,5 @@ Makefile.in
/unittests
/tester.py
+# /doc/
+/doc/doxygen
diff --git a/Doxyfile b/Doxyfile
new file mode 100644
index 0000000..ba1d24a
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,1418 @@
+# Doxyfile 1.5.6
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = obfpsroxy
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = alpha
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = ./doc/doxygen
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
+# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
+# and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = NO
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+# DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page. This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = src/
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS = *.c \
+ *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html) You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs for obfsproxy"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.torproject.Tor
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to FRAME, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature. Other possible values
+# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
+# and Class Hiererachy pages using a tree view instead of an ordered list;
+# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
+# disables this behavior completely. For backwards compatibility with previous
+# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
+# respectively.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# By default doxygen will write a font called FreeSans.ttf to the output
+# directory and reference it in all dot files that doxygen generates. This
+# font does not include all possible unicode characters however, so when you need
+# these (or just want a differently looking font) you can specify the font name
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME = FreeSans
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is enabled by default, which results in a transparent
+# background. Warning: Depending on the platform used, enabling this option
+# may lead to badly anti-aliased labels on the edges of a graph (i.e. they
+# become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/Makefile.am b/Makefile.am
index 1be20d1..963c725 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -58,6 +58,9 @@ EXTRA_DIST = doc/protocol-spec.txt
TESTS = unittests
+doxygen:
+ doxygen && cd doc/doxygen/latex && make
+
if HAVE_PYTHON
TESTS += tester.py
noinst_PROGRAMS += tester.py
1
0
[obfsproxy/master] Add brief file-level documentation for all source files.
by nickm@torproject.org 12 Dec '11
by nickm@torproject.org 12 Dec '11
12 Dec '11
commit 6016f54a961d51fe8a2fc2bbee18d41d0127d092
Author: George Kadianakis <desnacked(a)gmail.com>
Date: Sun Dec 11 05:18:59 2011 +0100
Add brief file-level documentation for all source files.
---
Doxyfile | 2 +-
src/container.h | 5 +++++
src/crypt.c | 6 ++++++
src/crypt.h | 5 +++++
src/external.c | 6 ++++++
src/external.h | 5 +++++
src/ht.h | 5 +++++
src/main.c | 11 +++++++++++
src/main.h | 6 ++++++
src/managed.c | 6 ++++++
src/managed.h | 5 +++++
src/network.c | 8 ++++++++
src/network.h | 5 +++++
src/obfs_main.c | 6 ++++++
src/protocol.c | 9 +++++++++
src/protocol.h | 5 +++++
src/protocols/dummy.c | 7 +++++++
src/protocols/dummy.h | 6 ++++++
src/protocols/obfs2.c | 7 +++++++
src/protocols/obfs2.h | 5 +++++
src/sha256.c | 13 ++++++++++---
src/sha256.h | 8 +++++++-
src/socks.c | 6 ++++++
src/socks.h | 5 +++++
src/test/tester.py.in | 14 ++++++++------
src/util.c | 6 ++++++
src/util.h | 5 +++++
27 files changed, 166 insertions(+), 11 deletions(-)
diff --git a/Doxyfile b/Doxyfile
index ba1d24a..a479ab2 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -534,7 +534,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
-INPUT = src/
+INPUT = src/ src/protocols/
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
diff --git a/src/container.h b/src/container.h
index 129e4f9..ff5b9e2 100644
--- a/src/container.h
+++ b/src/container.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2011, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * \file container.h
+ * \brief Headers for container.c.
+ **/
+
#ifndef CONTAINER_H
#define CONTAINER_H
diff --git a/src/crypt.c b/src/crypt.c
index 62d99fe..b8240be 100644
--- a/src/crypt.c
+++ b/src/crypt.c
@@ -2,6 +2,12 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file crypt.c
+ * \headerfile crypt.h
+ * \brief Cryptographic functions.
+ **/
+
#include "util.h"
#define CRYPT_PRIVATE
diff --git a/src/crypt.h b/src/crypt.h
index 51bbc57..bf20803 100644
--- a/src/crypt.h
+++ b/src/crypt.h
@@ -2,6 +2,11 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file crypt.h
+ * \brief Headers for crypt.c.
+ **/
+
#ifndef CRYPT_H
#define CRYPT_H
diff --git a/src/external.c b/src/external.c
index e05deca..3a79909 100644
--- a/src/external.c
+++ b/src/external.c
@@ -2,6 +2,12 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file external.c
+ * \headerfile external.h
+ * \brief Implements the 'external proxy' mode of obfsproxy.
+ **/
+
#include "util.h"
#include "container.h"
diff --git a/src/external.h b/src/external.h
index 6bfcb46..d9d987c 100644
--- a/src/external.h
+++ b/src/external.h
@@ -2,6 +2,11 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file external.h
+ * \brief Headers for external.c.
+ **/
+
#ifndef EXTERNAL_H
#define EXTERNAL_H
diff --git a/src/ht.h b/src/ht.h
index 8c45db1..6733612 100644
--- a/src/ht.h
+++ b/src/ht.h
@@ -3,6 +3,11 @@
* Copyright (c) 2007-2011, The Tor Project, Inc. */
/* See license at end. */
+/**
+ * \file ht.h
+ * \brief Hash table functions.
+ **/
+
/* Based on ideas by Christopher Clark and interfaces from Niels Provos. */
#ifndef HT_H
diff --git a/src/main.c b/src/main.c
index c7515a2..e03daf0 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2,6 +2,17 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file main.c
+ * \headerfile main.h
+ * \brief Entry point of obfsproxy. Does command-line parsing, and
+ * switches into 'external' or 'managed' proxy mode.
+ *
+ * (Practically, obfs_main.c is the actual entry point of obfsproxy,
+ * but all it does is call obfs_main().)
+ **/
+
+
#include "util.h"
#include "container.h"
diff --git a/src/main.h b/src/main.h
index 538cfdd..65900b3 100644
--- a/src/main.h
+++ b/src/main.h
@@ -2,6 +2,12 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file main.h
+ * \brief Headers for main.c.
+ **/
+
+
#ifndef MAIN_H
#define MAIN_H
diff --git a/src/managed.c b/src/managed.c
index 99f8290..71658dc 100644
--- a/src/managed.c
+++ b/src/managed.c
@@ -2,6 +2,12 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file managed.c
+ * \headerfile managed.h
+ * \brief Implements the 'managed proxy' mode of obfsproxy.
+ **/
+
#include "util.h"
#define MANAGED_PRIVATE
diff --git a/src/managed.h b/src/managed.h
index 2b14c2b..34382f5 100644
--- a/src/managed.h
+++ b/src/managed.h
@@ -2,6 +2,11 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file managed.h
+ * \brief Headers for managed.c.
+ **/
+
#ifndef MANAGED_H
#define MANAGED_H
diff --git a/src/network.c b/src/network.c
index a1fbe41..5c3cedf 100644
--- a/src/network.c
+++ b/src/network.c
@@ -2,6 +2,14 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file network.c
+ * \headerfile network.h
+ * \brief Networking side of obfspoxy. Creates listeners, accepts
+ * connections, reads/writes data, and calls transport callbacks when
+ * applicable.
+ **/
+
#include "util.h"
#define NETWORK_PRIVATE
diff --git a/src/network.h b/src/network.h
index 97e3d8c..825a91e 100644
--- a/src/network.h
+++ b/src/network.h
@@ -2,6 +2,11 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file network.h
+ * \brief Headers for network.c.
+ **/
+
#ifndef NETWORK_H
#define NETWORK_H
diff --git a/src/obfs_main.c b/src/obfs_main.c
index c891e05..f787d69 100644
--- a/src/obfs_main.c
+++ b/src/obfs_main.c
@@ -2,6 +2,12 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file obfs_main.c
+ * \brief Real entry point of obfsproxy. Immediately calls
+ * main.c:obfs_main().
+ **/
+
int obfs_main(int argc, char *argv[]);
/**
diff --git a/src/protocol.c b/src/protocol.c
index 81fd454..4abff90 100644
--- a/src/protocol.c
+++ b/src/protocol.c
@@ -2,6 +2,15 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file protocol.c
+ * \headerfile protocol.h
+ * \brief Pluggable transports-related functions. Acts as a wrapper on
+ * top of transport callbacks and transport-specific option parsing.
+ *
+ * 'Protocol' is a synonym to 'pluggable transport' in obfsproxy code.
+ **/
+
#include "util.h"
#include "network.h"
#include "protocol.h"
diff --git a/src/protocol.h b/src/protocol.h
index d360594..2dcc535 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -2,6 +2,11 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file protocol.h
+ * \brief Headers for protocol.c.
+ **/
+
#ifndef PROTOCOL_H
#define PROTOCOL_H
diff --git a/src/protocols/dummy.c b/src/protocols/dummy.c
index 21fd3ca..f27f48b 100644
--- a/src/protocols/dummy.c
+++ b/src/protocols/dummy.c
@@ -2,6 +2,13 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file dummy.c
+ * \headerfile dummy.h
+ * \brief Implements the 'dummy' pluggable transport. A testing-only
+ * pluggable transport that leaves traffic intact
+ **/
+
#include "util.h"
#define PROTOCOL_DUMMY_PRIVATE
diff --git a/src/protocols/dummy.h b/src/protocols/dummy.h
index 3dc1995..150b3ff 100644
--- a/src/protocols/dummy.h
+++ b/src/protocols/dummy.h
@@ -1,6 +1,12 @@
/* Copyright 2011 Nick Mathewson, George Kadianakis
See LICENSE for other credits and copying information
*/
+
+/**
+ * \file dummy.h
+ * \brief Headers for dummy.c.
+ **/
+
#ifndef PROTOCOL_DUMMY_H
#define PROTOCOL_DUMMY_H
diff --git a/src/protocols/obfs2.c b/src/protocols/obfs2.c
index 6e241c3..de26858 100644
--- a/src/protocols/obfs2.c
+++ b/src/protocols/obfs2.c
@@ -2,6 +2,13 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file obfs2.c
+ * \headerfile obfs2.h
+ * \brief Implements the 'obfs2' pluggable transport.
+ **/
+
+
#include "util.h"
#define PROTOCOL_OBFS2_PRIVATE
diff --git a/src/protocols/obfs2.h b/src/protocols/obfs2.h
index fb07407..6030c79 100644
--- a/src/protocols/obfs2.h
+++ b/src/protocols/obfs2.h
@@ -2,6 +2,11 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file obfs2.h
+ * \brief Headers for obfs2.c.
+ **/
+
#ifndef PROTOCOL_OBFS2_H
#define PROTOCOL_OBFS2_H
diff --git a/src/sha256.c b/src/sha256.c
index 8d835d4..349cdeb 100644
--- a/src/sha256.c
+++ b/src/sha256.c
@@ -1,8 +1,15 @@
/* Copyright (c) 2009-2011, The Tor Project, Inc. */
/* See the LICENSE file for licensing information */
-/* This SHA256 implementation is adapted from the public domain one in
- LibTomCrypt, version 1.6. Tor uses it on platforms where OpenSSL doesn't
- have a SHA256. */
+
+/**
+ * \file sha256.c
+ * \headerfile sha256.h
+ * \brief SHA256 implementation by Tom St Denis.
+ *
+ * This SHA256 implementation is adapted from the public domain one in
+ * LibTomCrypt, version 1.6. Tor uses it on platforms where OpenSSL
+ * doesn't have a SHA256.
+ **/
#include "util.h"
diff --git a/src/sha256.h b/src/sha256.h
index 6afdbfe..033f00d 100644
--- a/src/sha256.h
+++ b/src/sha256.h
@@ -1,4 +1,10 @@
-/* Header file for the fallback (libtomcrypt) implementation of SHA256. */
+/* See the LICENSE file for licensing information */
+
+/**
+ * \file sha256.h
+ * \brief Headers for sha256.c.
+ **/
+
#ifndef SHA256_H
#define SHA256_H
diff --git a/src/socks.c b/src/socks.c
index 46bc5d5..51c6dff 100644
--- a/src/socks.c
+++ b/src/socks.c
@@ -2,6 +2,12 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file socks.c
+ * \headerfile socks.h
+ * \brief SOCKS{5,4,4a} server.
+ **/
+
#include "util.h"
#define SOCKS_PRIVATE
diff --git a/src/socks.h b/src/socks.h
index a06a11e..4e0bdfa 100644
--- a/src/socks.h
+++ b/src/socks.h
@@ -2,6 +2,11 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file socks.h
+ * \brief Headers for socks.c.
+ **/
+
#ifndef SOCKS_H
#define SOCKS_H
diff --git a/src/test/tester.py.in b/src/test/tester.py.in
index 4b93784..ea46d1f 100644
--- a/src/test/tester.py.in
+++ b/src/test/tester.py.in
@@ -1,11 +1,13 @@
#! @PYTHON@
-# Integration tests for obfsproxy.
-#
-# The obfsproxy binary is assumed to exist in the current working
-# directory, and you need to have Python 2.6 or better (but not 3).
-# You need to be able to make connections to arbitrary high-numbered
-# TCP ports on the loopback interface.
+"""@package tester.py.in
+Integration tests for obfsproxy.
+
+The obfsproxy binary is assumed to exist in the current working
+directory, and you need to have Python 2.6 or better (but not 3).
+You need to be able to make connections to arbitrary high-numbered
+TCP ports on the loopback interface.
+"""
import difflib
import errno
diff --git a/src/util.c b/src/util.c
index f56ba58..db0dc77 100644
--- a/src/util.c
+++ b/src/util.c
@@ -2,6 +2,12 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file util.c
+ * \headerfile util.h
+ * \brief Utility functions.
+ **/
+
#include "util.h"
#include <errno.h>
diff --git a/src/util.h b/src/util.h
index 2b37c48..8a7585b 100644
--- a/src/util.h
+++ b/src/util.h
@@ -2,6 +2,11 @@
See LICENSE for other credits and copying information
*/
+/**
+ * \file util.h
+ * \brief Headers for util.c.
+ **/
+
#ifndef UTIL_H
#define UTIL_H
1
0
12 Dec '11
commit fec1360c7a20e7d06b7c12946e7ffd10286a67db
Author: George Kadianakis <desnacked(a)gmail.com>
Date: Mon Dec 12 11:36:17 2011 +0100
Add detailed file-level documentation.
---
Doxyfile | 2 +-
src/crypt.c | 2 +
src/main.c | 5 +--
src/managed.c | 8 ++++++
src/network.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++
src/obfs_main.c | 3 ++
src/protocol.c | 10 ++++++--
src/protocols/dummy.h | 3 ++
src/protocols/obfs2.c | 19 +++++++++++++++-
src/protocols/obfs2.h | 17 ++++++++++++++
src/sha256.c | 6 ++--
src/socks.c | 58 +++++++++++++++++++++++++++++++-----------------
src/util.c | 6 +++++
13 files changed, 162 insertions(+), 32 deletions(-)
diff --git a/Doxyfile b/Doxyfile
index a479ab2..b2e21c1 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -1118,7 +1118,7 @@ PERLMOD_MAKEVAR_PREFIX =
# evaluate all C-preprocessor directives found in the sources and include
# files.
-ENABLE_PREPROCESSING = YES
+ENABLE_PREPROCESSING = NO
# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
# names in the source code. If set to NO (the default) only conditional
diff --git a/src/crypt.c b/src/crypt.c
index b8240be..e70ec29 100644
--- a/src/crypt.c
+++ b/src/crypt.c
@@ -6,6 +6,8 @@
* \file crypt.c
* \headerfile crypt.h
* \brief Cryptographic functions.
+ *
+ * \details Most functions here are wrappers of OpenSSL functions.
**/
#include "util.h"
diff --git a/src/main.c b/src/main.c
index e03daf0..76158e0 100644
--- a/src/main.c
+++ b/src/main.c
@@ -8,11 +8,10 @@
* \brief Entry point of obfsproxy. Does command-line parsing, and
* switches into 'external' or 'managed' proxy mode.
*
- * (Practically, obfs_main.c is the actual entry point of obfsproxy,
- * but all it does is call obfs_main().)
+ * \details Practically, obfs_main.c is the actual entry point of
+ * obfsproxy, but all it really does is call obfs_main().
**/
-
#include "util.h"
#include "container.h"
diff --git a/src/managed.c b/src/managed.c
index 71658dc..d70c1cf 100644
--- a/src/managed.c
+++ b/src/managed.c
@@ -6,6 +6,14 @@
* \file managed.c
* \headerfile managed.h
* \brief Implements the 'managed proxy' mode of obfsproxy.
+ *
+ * \details This is an implementation of managed proxies according to
+ * the 180-pluggable-transport.txt specification. The entry point is
+ * launch_managed_proxy() where a managed_proxy_t instance is created
+ * to represent our managed proxy. We read and validate the
+ * environment variables that tor should have prepared for us, launch
+ * the appropriate listeners, and finally kickstart libevent to start
+ * accepting connections.
**/
#include "util.h"
diff --git a/src/network.c b/src/network.c
index 5c3cedf..3ede3ab 100644
--- a/src/network.c
+++ b/src/network.c
@@ -8,6 +8,61 @@
* \brief Networking side of obfspoxy. Creates listeners, accepts
* connections, reads/writes data, and calls transport callbacks when
* applicable.
+ *
+ * \details Terminology:
+ *
+ * A <em>connection</em> is a bidirectional communications channel,
+ * usually backed by a network socket, and represented in this layer
+ * by a conn_t, wrapping a libevent bufferevent.
+ *
+ * A <em>circuit</em> is a <b>pair</b> of connections, referred to as the
+ * <em>upstream</em> and <em>downstream</em> connections. A circuit
+ * is represented by a circuit_t. The upstream connection of a
+ * circuit communicates in cleartext with the higher-level program
+ * that wishes to make use of our obfuscation service. The
+ * downstream connection commmunicates in an obfuscated fashion with
+ * the remote peer that the higher-level client wishes to contact.
+ *
+ * A <em>listener</em> is a listening socket bound to a particular
+ * obfuscation protocol, represented in this layer by a listener_t
+ * and its config_t. Connecting to a listener creates one
+ * connection of a circuit, and causes this program to initiate the
+ * other connection (possibly after receiving in-band instructions
+ * about where to connect to). A listener is said to be a
+ * <em>client</em> listener if connecting to it creates the
+ * <b>upstream</b> connection, and a <em>server</em> listener if
+ * connecting to it creates the <b>downstream</b> connection.
+ *
+ * There are two kinds of client listeners: a <em>simple</em> client
+ * listener always connects to the same remote peer every time it
+ * needs to initiate a downstream connection; a <em>socks</em>
+ * client listener can be told to connect to an arbitrary remote
+ * peer using the SOCKS protocol (version 4 or 5).
+ *
+ * The diagram below might help demonstrate the relationship between
+ * connections and circuits:
+ *
+ *\verbatim
+ downstream
+
+ 'circuit_t C' 'conn_t CD' 'conn_t SD' 'circuit_t S'
+ +-----------+ +-----------+
+ upstream ----|obfsproxy c|-------------|obfsproxy s|---- upstream
+ | +-----------+ +-----------+ |
+ 'conn_t CU'| |'conn_t SU'
+ +------------+ +--------------+
+ | Tor Client | | Tor Bridge |
+ +------------+ +--------------+
+
+ \endverbatim
+ *
+ * In the above diagram, <b>obfsproxy c</b> is the client-side
+ * obfsproxy, and <b>obfsproxy s</b> is the server-side
+ * obfsproxy. <b>conn_t CU</b> is the Client's Upstream connection,
+ * the communication channel between tor and obfsproxy. <b>conn_t
+ * CD</b> is the Client's Downstream connection, the communication
+ * channel between obfsproxy and the remote peer. These two
+ * connections form <b>circuit_t C</b>.
**/
#include "util.h"
diff --git a/src/obfs_main.c b/src/obfs_main.c
index f787d69..08399eb 100644
--- a/src/obfs_main.c
+++ b/src/obfs_main.c
@@ -6,6 +6,9 @@
* \file obfs_main.c
* \brief Real entry point of obfsproxy. Immediately calls
* main.c:obfs_main().
+ *
+ * \details This all happens so that our unittests binary can link
+ * against main.c.
**/
int obfs_main(int argc, char *argv[]);
diff --git a/src/protocol.c b/src/protocol.c
index 4abff90..4b97d4e 100644
--- a/src/protocol.c
+++ b/src/protocol.c
@@ -5,10 +5,14 @@
/**
* \file protocol.c
* \headerfile protocol.h
- * \brief Pluggable transports-related functions. Acts as a wrapper on
- * top of transport callbacks and transport-specific option parsing.
+ * \brief Pluggable transports-related functions.
*
- * 'Protocol' is a synonym to 'pluggable transport' in obfsproxy code.
+ * \details Acts as an intermediary between generic obfsproxy code,
+ * and pluggable transports code. Provides wrappers for
+ * transport-specific configuration, and callbacks.
+ *
+ * Note that in obfsproxy code, 'protocol' is a synonym to 'pluggable
+ * transport'.
**/
#include "util.h"
diff --git a/src/protocols/dummy.h b/src/protocols/dummy.h
index 150b3ff..b5cb3a6 100644
--- a/src/protocols/dummy.h
+++ b/src/protocols/dummy.h
@@ -28,6 +28,7 @@ extern const protocol_vtable dummy_vtable;
also because, if you're using dummy as a template, you probably
will want to extend the generic structures. */
+/** \private \extends config_t */
typedef struct dummy_config_t {
config_t super;
struct evutil_addrinfo *listen_addr;
@@ -35,10 +36,12 @@ typedef struct dummy_config_t {
enum listen_mode mode;
} dummy_config_t;
+/** \private \extends conn_t */
typedef struct dummy_conn_t {
conn_t super;
} dummy_conn_t;
+/** \private \extends circuit_t */
typedef struct dummy_circuit_t {
circuit_t super;
} dummy_circuit_t;
diff --git a/src/protocols/obfs2.c b/src/protocols/obfs2.c
index de26858..213e36f 100644
--- a/src/protocols/obfs2.c
+++ b/src/protocols/obfs2.c
@@ -6,9 +6,26 @@
* \file obfs2.c
* \headerfile obfs2.h
* \brief Implements the 'obfs2' pluggable transport.
+ *
+ * \details We track the state of the obfs2 protocol in the
+ * <b>state</b> member of <b>obfs2_state_t</b>.
+ *
+ * The first step of the obfs2 protocol, is to send the handshake
+ * message (obfs2_handshake()) and move to the initial state which is
+ * <em>ST_WAIT_FOR_KEY</em>.
+ *
+ * During <em>ST_WAIT_FOR_KEY</em>, we are waiting for the key of our
+ * peer. obfs2_recv() is responsible for picking up the key from our
+ * peer's handshake message, deriving additional keys out of it
+ * (init_crypto()), and progressing to the <em>ST_WAIT_FOR_PADDING</em> state.
+ *
+ * During <em>ST_WAIT_FOR_PADDING</em>, we are waiting for the amount
+ * of padding that our peer promised in his handshake message. When we
+ * receive the padding, we move to the final state <em>ST_OPEN</em>
+ * and start exchanging data messages with our peer using the derived
+ * keys.
**/
-
#include "util.h"
#define PROTOCOL_OBFS2_PRIVATE
diff --git a/src/protocols/obfs2.h b/src/protocols/obfs2.h
index 6030c79..74b65a1 100644
--- a/src/protocols/obfs2.h
+++ b/src/protocols/obfs2.h
@@ -74,20 +74,37 @@ typedef struct obfs2_state_t {
int padding_left_to_read;
} obfs2_state_t;
+/** config_t for obfs2.
+ * \private \extends config_t
+ */
typedef struct obfs2_config_t {
+ /** Base <b>config_t</b>. */
config_t super;
+ /** Address to listen on. */
struct evutil_addrinfo *listen_addr;
+ /** Address to connect to. */
struct evutil_addrinfo *target_addr;
+ /** Listener mode. */
enum listen_mode mode;
+ /** obfs2 shared secret. */
uchar shared_secret[SHARED_SECRET_LENGTH];
} obfs2_config_t;
+/** conn_t for obfs2.
+ * \private \extends conn_t
+ */
typedef struct obfs2_conn_t {
+ /** Base <b>conn_t</b>. */
conn_t super;
} obfs2_conn_t;
+/** circuit_t for obfs2.
+ * \private \extends circuit_t
+ */
typedef struct obfs2_circuit_t {
+ /** Base <b>circuit_t</b>. */
circuit_t super;
+ /** State of obfs2 for this circuit. */
obfs2_state_t *state;
} obfs2_circuit_t;
diff --git a/src/sha256.c b/src/sha256.c
index 349cdeb..f6bbd7a 100644
--- a/src/sha256.c
+++ b/src/sha256.c
@@ -6,9 +6,9 @@
* \headerfile sha256.h
* \brief SHA256 implementation by Tom St Denis.
*
- * This SHA256 implementation is adapted from the public domain one in
- * LibTomCrypt, version 1.6. Tor uses it on platforms where OpenSSL
- * doesn't have a SHA256.
+ * \details This SHA256 implementation is adapted from the public
+ * domain one in LibTomCrypt, version 1.6. Tor uses it on platforms
+ * where OpenSSL doesn't have a SHA256.
**/
#include "util.h"
diff --git a/src/socks.c b/src/socks.c
index 51c6dff..98cb678 100644
--- a/src/socks.c
+++ b/src/socks.c
@@ -6,6 +6,43 @@
* \file socks.c
* \headerfile socks.h
* \brief SOCKS{5,4,4a} server.
+ *
+ * \details
+ * Every <b>circuit_t</b> has a <b>socks_state_t</b> attached
+ * to it, representing the state of the SOCKS protocol on that
+ * circuit.
+ *
+ * If we are a client using SOCKS, and we haven't completed the SOCKS
+ * handshake, socks_read_cb() passes all incoming data to
+ * handle_socks(). On a valid 'Client request' packet, we parse the
+ * requested address into <b>struct parsereq</b> of
+ * <b>socks_state_t</b>, and toggle SOCKS' state to ST_HAVE_ADDR. When
+ * socks_read_cb() notices that we are in ST_HAVE_ADDR, it connects to
+ * the requested address to set up the proxying tunnel. Upon a
+ * successful connection, pending_socks_cb() sends back a 'Server
+ * reply' and sets up the proxying tunnel.
+ *
+ * <em>SOCKS5 protocol handshake:</em>
+ *
+ * Client ------------------------> Server\n
+ * Method Negotiation Packet (socks5_handle_negotiation())
+ *
+ * Client <------------------------ Server\n
+ * Method Negotiation Reply (socks5_do_negotiation())
+ *
+ * Client ------------------------> Server\n
+ * Client request (socks5_handle_request())
+ *
+ * Client <------------------------ Server\n
+ * Server reply (socks5_send_reply())
+ *
+ * <em>SOCKS{4,4a} protocol handshake:</em>
+ *
+ * Client ------------------------> Server\n
+ * Client Request (socks4_read_request())
+ *
+ * Client <------------------------ Server\n
+ * Server reply (socks4_send_reply())
**/
#include "util.h"
@@ -17,27 +54,6 @@
#include <event2/buffer.h>
-/**
- General SOCKS5 idea:
-
- Client ------------------------> Server
- Method Negotiation Packet
-
- Client <------------------------ Server
- Method Negotiation Reply
-
- Client ------------------------> Server
- Client request
-
- Client <------------------------ Server
- Server reply
-
- "Method Negotiation Packet" is handled by: socks5_handle_negotiation()
- "Method Negotiation Reply" is done by: socks5_do_negotiation()
- "Client request" is handled by: socks5_handle_request()
- "Server reply" is done by: socks5_send_reply()
-*/
-
typedef unsigned char uchar;
diff --git a/src/util.c b/src/util.c
index db0dc77..c63a651 100644
--- a/src/util.c
+++ b/src/util.c
@@ -6,6 +6,12 @@
* \file util.c
* \headerfile util.h
* \brief Utility functions.
+ *
+ * \details Contains:
+ * - wrappers of malloc() et al.
+ * - network functions
+ * - string functions
+ * - functions used by obfsproxy's logging subsystem
**/
#include "util.h"
1
0
[doctor/master] Remove an unnecessary word in a status message.
by karsten@torproject.org 12 Dec '11
by karsten@torproject.org 12 Dec '11
12 Dec '11
commit ccca2e76026b095a072b2f6975d40590f737f1bf
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Mon Dec 12 15:38:45 2011 +0100
Remove an unnecessary word in a status message.
---
src/org/torproject/doctor/StatusFileReport.java | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/org/torproject/doctor/StatusFileReport.java b/src/org/torproject/doctor/StatusFileReport.java
index a43a27e..884dc18 100755
--- a/src/org/torproject/doctor/StatusFileReport.java
+++ b/src/org/torproject/doctor/StatusFileReport.java
@@ -147,7 +147,7 @@ public class StatusFileReport implements Report {
case ConsensusMissingSignatures:
warningStrings.put("The consensuses downloaded from the "
+ "following authorities are missing signatures from "
- + "other, previously voting authorities: " + details,
+ + "previously voting authorities: " + details,
150L * 60L * 1000L);
break;
}
1
0