[tor-commits] [onionoo/master] Support IPv6 addresses in summary, details, and search.

karsten at torproject.org karsten at torproject.org
Fri Jun 15 12:54:26 UTC 2012


commit 74124548ee325d2689c2d25142f15b7572cb623a
Author: Karsten Loesing <karsten.loesing at 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;



More information about the tor-commits mailing list