commit 74124548ee325d2689c2d25142f15b7572cb623a Author: Karsten Loesing karsten.loesing@gmx.net Date: Fri Jun 15 14:50:52 2012 +0200
Support IPv6 addresses in summary, details, and search.
Implements #5245. --- src/org/torproject/onionoo/CurrentNodes.java | 71 +++++++++++++++------- src/org/torproject/onionoo/DetailDataWriter.java | 29 ++++++++- src/org/torproject/onionoo/Node.java | 34 ++++++++++- src/org/torproject/onionoo/ResourceServlet.java | 5 +- 4 files changed, 110 insertions(+), 29 deletions(-)
diff --git a/src/org/torproject/onionoo/CurrentNodes.java b/src/org/torproject/onionoo/CurrentNodes.java index c6b4d8a..4da7133 100644 --- a/src/org/torproject/onionoo/CurrentNodes.java +++ b/src/org/torproject/onionoo/CurrentNodes.java @@ -62,6 +62,7 @@ public class CurrentNodes { String fingerprint = parts[2]; String addresses = parts[3]; String address; + SortedSet<String> orAddressesAndPorts = new TreeSet<String>(); SortedSet<String> exitAddresses = new TreeSet<String>(); if (addresses.contains(";")) { String[] addressParts = addresses.split(";", -1); @@ -72,6 +73,10 @@ public class CurrentNodes { System.exit(1); } address = addressParts[0]; + if (addressParts[1].length() > 0) { + orAddressesAndPorts.addAll(Arrays.asList( + addressParts[1].split("\+"))); + } if (addressParts[2].length() > 0) { exitAddresses.addAll(Arrays.asList( addressParts[2].split("\+"))); @@ -94,11 +99,13 @@ public class CurrentNodes { countryCode = parts[10]; } if (isRelay) { - this.addRelay(nickname, fingerprint, address, exitAddresses, + this.addRelay(nickname, fingerprint, address, + orAddressesAndPorts, exitAddresses, publishedOrValidAfterMillis, orPort, dirPort, relayFlags, consensusWeight, countryCode); } else { - this.addBridge(nickname, fingerprint, address, exitAddresses, + this.addBridge(nickname, fingerprint, address, + orAddressesAndPorts, exitAddresses, publishedOrValidAfterMillis, orPort, dirPort, relayFlags, consensusWeight, countryCode); } @@ -134,8 +141,14 @@ public class CurrentNodes { String fingerprint = entry.getFingerprint(); String address = entry.getAddress(); StringBuilder addressesBuilder = new StringBuilder(); - addressesBuilder.append(address + ";;"); + addressesBuilder.append(address + ";"); int written = 0; + for (String orAddressAndPort : entry.getOrAddressesAndPorts()) { + addressesBuilder.append((written++ > 0 ? "+" : "") + + orAddressAndPort); + } + addressesBuilder.append(";"); + written = 0; for (String exitAddress : entry.getExitAddresses()) { addressesBuilder.append((written++ > 0 ? "+" : "") + exitAddress); @@ -164,6 +177,14 @@ public class CurrentNodes { String published = dateTimeFormat.format( entry.getLastSeenMillis()); String address = entry.getAddress(); + StringBuilder addressesBuilder = new StringBuilder(); + addressesBuilder.append(address + ";"); + int written = 0; + for (String orAddressAndPort : entry.getOrAddressesAndPorts()) { + addressesBuilder.append((written++ > 0 ? "+" : "") + + orAddressAndPort); + } + addressesBuilder.append(";"); String orPort = String.valueOf(entry.getOrPort()); String dirPort = String.valueOf(entry.getDirPort()); StringBuilder sb = new StringBuilder(); @@ -171,9 +192,9 @@ public class CurrentNodes { sb.append("," + relayFlag); } String relayFlags = sb.toString().substring(1); - bw.write("b " + nickname + " " + fingerprint + " " + address - + ";; " + published + " " + orPort + " " + dirPort + " " - + relayFlags + " -1 ??\n"); + bw.write("b " + nickname + " " + fingerprint + " " + + addressesBuilder.toString() + " " + published + " " + orPort + + " " + dirPort + " " + relayFlags + " -1 ??\n"); } bw.close(); } catch (IOException e) { @@ -227,28 +248,30 @@ public class CurrentNodes { String nickname = entry.getNickname(); String fingerprint = entry.getFingerprint(); String address = entry.getAddress(); + SortedSet<String> orAddressesAndPorts = new TreeSet<String>( + entry.getOrAddresses()); int orPort = entry.getOrPort(); int dirPort = entry.getDirPort(); SortedSet<String> relayFlags = entry.getFlags(); long consensusWeight = entry.getBandwidth(); - this.addRelay(nickname, fingerprint, address, null, - validAfterMillis, orPort, dirPort, relayFlags, consensusWeight, - null); + this.addRelay(nickname, fingerprint, address, orAddressesAndPorts, + null, validAfterMillis, orPort, dirPort, relayFlags, + consensusWeight, null); } }
public void addRelay(String nickname, String fingerprint, - String address, SortedSet<String> exitAddresses, - long validAfterMillis, int orPort, int dirPort, - SortedSet<String> relayFlags, long consensusWeight, + String address, SortedSet<String> orAddressesAndPorts, + SortedSet<String> exitAddresses, long validAfterMillis, int orPort, + int dirPort, SortedSet<String> relayFlags, long consensusWeight, String countryCode) { if (validAfterMillis >= cutoff && (!this.currentRelays.containsKey(fingerprint) || this.currentRelays.get(fingerprint).getLastSeenMillis() < validAfterMillis)) { - Node entry = new Node(nickname, fingerprint, address, exitAddresses, - validAfterMillis, orPort, dirPort, relayFlags, consensusWeight, - countryCode); + Node entry = new Node(nickname, fingerprint, address, + orAddressesAndPorts, exitAddresses, validAfterMillis, orPort, + dirPort, relayFlags, consensusWeight, countryCode); this.currentRelays.put(fingerprint, entry); if (validAfterMillis > this.lastValidAfterMillis) { this.lastValidAfterMillis = validAfterMillis; @@ -339,26 +362,28 @@ public class CurrentNodes { String nickname = entry.getNickname(); String fingerprint = entry.getFingerprint(); String address = entry.getAddress(); + SortedSet<String> orAddressesAndPorts = new TreeSet<String>( + entry.getOrAddresses()); int orPort = entry.getOrPort(); int dirPort = entry.getDirPort(); SortedSet<String> relayFlags = entry.getFlags(); - this.addBridge(nickname, fingerprint, address, null, - publishedMillis, orPort, dirPort, relayFlags, -1, "??"); + this.addBridge(nickname, fingerprint, address, orAddressesAndPorts, + null, publishedMillis, orPort, dirPort, relayFlags, -1, "??"); } }
public void addBridge(String nickname, String fingerprint, - String address, SortedSet<String> exitAddresses, - long publishedMillis, int orPort, int dirPort, - SortedSet<String> relayFlags, long consensusWeight, + String address, SortedSet<String> orAddressesAndPorts, + SortedSet<String> exitAddresses, long publishedMillis, int orPort, + int dirPort, SortedSet<String> relayFlags, long consensusWeight, String countryCode) { if (publishedMillis >= cutoff && (!this.currentBridges.containsKey(fingerprint) || this.currentBridges.get(fingerprint).getLastSeenMillis() < publishedMillis)) { - Node entry = new Node(nickname, fingerprint, address, exitAddresses, - publishedMillis, orPort, dirPort, relayFlags, consensusWeight, - countryCode); + Node entry = new Node(nickname, fingerprint, address, + orAddressesAndPorts, exitAddresses, publishedMillis, orPort, + dirPort, relayFlags, consensusWeight, countryCode); this.currentBridges.put(fingerprint, entry); if (publishedMillis > this.lastPublishedMillis) { this.lastPublishedMillis = publishedMillis; diff --git a/src/org/torproject/onionoo/DetailDataWriter.java b/src/org/torproject/onionoo/DetailDataWriter.java index cb4ebe6..6a724d8 100644 --- a/src/org/torproject/onionoo/DetailDataWriter.java +++ b/src/org/torproject/onionoo/DetailDataWriter.java @@ -19,6 +19,7 @@ import java.util.SortedMap; import java.util.SortedSet; import java.util.TimeZone; import java.util.TreeMap; +import java.util.TreeSet;
import org.apache.commons.lang.StringEscapeUtils;
@@ -309,8 +310,17 @@ public class DetailDataWriter { Node entry = relay.getValue(); String nickname = entry.getNickname(); String address = entry.getAddress(); + SortedSet<String> orAddresses = new TreeSet<String>( + entry.getOrAddressesAndPorts()); + orAddresses.add(address + ":" + entry.getOrPort()); + StringBuilder orAddressesAndPortsBuilder = new StringBuilder(); + int addressesWritten = 0; + for (String orAddress : orAddresses) { + orAddressesAndPortsBuilder.append( + (addressesWritten++ > 0 ? "," : "") + """ + orAddress + + """); + } String running = entry.getRunning() ? "true" : "false"; - int orPort = entry.getOrPort(); int dirPort = entry.getDirPort(); String countryCode = entry.getCountryCode(); String latitude = entry.getLatitude(); @@ -325,7 +335,8 @@ public class DetailDataWriter { sb.append("{"version":1,\n" + ""nickname":"" + nickname + "",\n" + ""fingerprint":"" + fingerprint + "",\n" - + ""or_addresses":["" + address + ":" + orPort + ""],\n" + + ""or_addresses":[" + orAddressesAndPortsBuilder.toString() + + "],\n" + ""dir_address":"" + address + ":" + dirPort + "",\n" + ""running":" + running + ",\n"); SortedSet<String> relayFlags = entry.getRelayFlags(); @@ -512,12 +523,22 @@ public class DetailDataWriter { String nickname = entry.getNickname(); String running = entry.getRunning() ? "true" : "false"; String address = entry.getAddress(); - int orPort = entry.getOrPort(); + SortedSet<String> orAddresses = new TreeSet<String>( + entry.getOrAddressesAndPorts()); + orAddresses.add(address + ":" + entry.getOrPort()); + StringBuilder orAddressesAndPortsBuilder = new StringBuilder(); + int addressesWritten = 0; + for (String orAddress : orAddresses) { + orAddressesAndPortsBuilder.append( + (addressesWritten++ > 0 ? "," : "") + """ + orAddress + + """); + } StringBuilder sb = new StringBuilder(); sb.append("{"version":1,\n" + ""nickname":"" + nickname + "",\n" + ""hashed_fingerprint":"" + fingerprint + "",\n" - + ""or_addresses":["" + address + ":" + orPort + ""],\n" + + ""or_addresses":[" + orAddressesAndPortsBuilder.toString() + + "],\n" + ""running":" + running + ","); SortedSet<String> relayFlags = entry.getRelayFlags(); if (!relayFlags.isEmpty()) { diff --git a/src/org/torproject/onionoo/Node.java b/src/org/torproject/onionoo/Node.java index f4e5e67..0bb4a23 100644 --- a/src/org/torproject/onionoo/Node.java +++ b/src/org/torproject/onionoo/Node.java @@ -16,6 +16,8 @@ public class Node { private String hashedFingerprint; private String nickname; private String address; + private SortedSet<String> orAddresses; + private SortedSet<String> orAddressesAndPorts; private SortedSet<String> exitAddresses; private String latitude; private String longitude; @@ -32,6 +34,7 @@ public class Node { private long consensusWeight; private boolean running; public Node(String nickname, String fingerprint, String address, + SortedSet<String> orAddressesAndPorts, SortedSet<String> exitAddresses, long lastSeenMillis, int orPort, int dirPort, SortedSet<String> relayFlags, long consensusWeight, String countryCode) { @@ -50,6 +53,13 @@ public class Node { this.exitAddresses.addAll(exitAddresses); } this.exitAddresses.remove(this.address); + this.orAddresses = new TreeSet<String>(); + this.orAddressesAndPorts = new TreeSet<String>(); + if (orAddressesAndPorts != null) { + for (String orAddressAndPort : orAddressesAndPorts) { + this.addOrAddressAndPort(orAddressAndPort); + } + } this.lastSeenMillis = lastSeenMillis; this.orPort = orPort; this.dirPort = dirPort; @@ -69,8 +79,30 @@ public class Node { public String getAddress() { return this.address; } + public SortedSet<String> getOrAddresses() { + return new TreeSet<String>(this.orAddresses); + } + public void addOrAddressAndPort(String orAddressAndPort) { + if (!orAddressAndPort.contains(":")) { + System.err.println("Illegal OR address:port '" + orAddressAndPort + + "'. Exiting."); + System.exit(1); + } else if (orAddressAndPort.length() > 0) { + String orAddress = orAddressAndPort.substring(0, + orAddressAndPort.lastIndexOf(":")); + if (this.exitAddresses.contains(orAddress)) { + this.exitAddresses.remove(orAddress); + } + this.orAddresses.add(orAddress); + this.orAddressesAndPorts.add(orAddressAndPort); + } + } + public SortedSet<String> getOrAddressesAndPorts() { + return new TreeSet<String>(this.orAddressesAndPorts); + } public void addExitAddress(String exitAddress) { - if (exitAddress.length() > 0 && !this.address.equals(exitAddress)) { + if (exitAddress.length() > 0 && !this.address.equals(exitAddress) && + !this.orAddresses.contains(exitAddress)) { this.exitAddresses.add(exitAddress); } } diff --git a/src/org/torproject/onionoo/ResourceServlet.java b/src/org/torproject/onionoo/ResourceServlet.java index 7ddd148..41f4c5a 100644 --- a/src/org/torproject/onionoo/ResourceServlet.java +++ b/src/org/torproject/onionoo/ResourceServlet.java @@ -118,6 +118,7 @@ public class ResourceServlet extends HttpServlet { String running = entry.getRunning() ? "true" : "false"; SortedSet<String> addresses = new TreeSet<String>(); addresses.add(entry.getAddress()); + addresses.addAll(entry.getOrAddresses()); addresses.addAll(entry.getExitAddresses()); StringBuilder addressesBuilder = new StringBuilder(); int written = 0; @@ -404,7 +405,9 @@ public class ResourceServlet extends HttpServlet { }
private static Pattern searchParameterPattern = - Pattern.compile("^\$?[0-9a-fA-F]{1,40}$|^[0-9a-zA-Z\.]{1,19}$"); + Pattern.compile("^\$?[0-9a-fA-F]{1,40}$|" /* Fingerprint. */ + + "^[0-9a-zA-Z\.]{1,19}$|" /* Nickname or IPv4 address. */ + + "^\[[0-9a-fA-F:\.]{1,39}\]?$"); /* IPv6 address. */ private String parseSearchParameter(String parameter) { if (!searchParameterPattern.matcher(parameter).matches()) { return null;
tor-commits@lists.torproject.org