commit a7d03e231499e37d82a47230886693a5d3127d20
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Tue Jul 24 14:46:50 2018 +0200
Add new "as_name" parameter.
Implements another part of #23713.
---
CHANGELOG.md | 1 +
.../org/torproject/onionoo/docs/DocumentStore.java | 3 +-
.../org/torproject/onionoo/docs/NodeStatus.java | 14 +++++++++
.../torproject/onionoo/docs/SummaryDocument.java | 14 ++++++++-
.../org/torproject/onionoo/server/NodeIndex.java | 10 +++++++
.../org/torproject/onionoo/server/NodeIndexer.java | 8 +++++
.../torproject/onionoo/server/RequestHandler.java | 29 ++++++++++++++++++
.../torproject/onionoo/server/ResourceServlet.java | 25 ++++++++++++++--
.../onionoo/updater/NodeDetailsStatusUpdater.java | 4 +++
.../onionoo/writer/SummaryDocumentWriter.java | 3 +-
.../onionoo/docs/SummaryDocumentTest.java | 1 +
.../onionoo/server/ResourceServletTest.java | 35 +++++++++++++++++++---
.../server/SummaryDocumentComparatorTest.java | 1 +
13 files changed, 138 insertions(+), 10 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9d0d091..89b36eb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@
bridges.
- Add "as" field as a copy of the "as_number" field in preparation
of removing the "as_number" field in the future.
+ - Add new "as_name" parameter to search relays by AS name.
# Changes in version 6.1-1.15.0 - 2018-07-16
diff --git a/src/main/java/org/torproject/onionoo/docs/DocumentStore.java b/src/main/java/org/torproject/onionoo/docs/DocumentStore.java
index b044788..8cf76c8 100644
--- a/src/main/java/org/torproject/onionoo/docs/DocumentStore.java
+++ b/src/main/java/org/torproject/onionoo/docs/DocumentStore.java
@@ -415,6 +415,7 @@ public class DocumentStore {
List<String> addresses = new ArrayList<>();
String countryCode = null;
String asNumber = null;
+ String asName = null;
String contact = null;
for (String orAddressAndPort : detailsDocument.getOrAddresses()) {
if (!orAddressAndPort.contains(":")) {
@@ -451,7 +452,7 @@ public class DocumentStore {
SummaryDocument summaryDocument = new SummaryDocument(isRelay,
nickname, fingerprint, addresses, lastSeenMillis, running,
relayFlags, consensusWeight, countryCode, firstSeenMillis,
- asNumber, contact, family, family, version, operatingSystem,
+ asNumber, asName, contact, family, family, version, operatingSystem,
hostName, verifiedHostNames, unverifiedHostNames,
recommendedVersion);
return summaryDocument;
diff --git a/src/main/java/org/torproject/onionoo/docs/NodeStatus.java b/src/main/java/org/torproject/onionoo/docs/NodeStatus.java
index 46da822..63720d9 100644
--- a/src/main/java/org/torproject/onionoo/docs/NodeStatus.java
+++ b/src/main/java/org/torproject/onionoo/docs/NodeStatus.java
@@ -387,6 +387,16 @@ public class NodeStatus extends Document {
return this.asNumber;
}
+ private String asName;
+
+ public void setAsName(String asName) {
+ this.asName = asName;
+ }
+
+ public String getAsName() {
+ return this.asName;
+ }
+
/* Reverse DNS lookup result */
private String hostName;
@@ -618,6 +628,9 @@ public class NodeStatus extends Document {
if (parts.length >= 26) {
nodeStatus.setVersionStatus(TorVersionStatus.ofAbbreviation(parts[25]));
}
+ if (parts.length >= 27) {
+ nodeStatus.setAsName(parts[26]);
+ }
return nodeStatus;
} catch (NumberFormatException e) {
log.error("Number format exception while parsing node "
@@ -688,6 +701,7 @@ public class NodeStatus extends Document {
.append((this.getHostName() != null ? this.getHostName() : ""));
sb.append("\t").append(null != this.getVersionStatus()
? this.getVersionStatus().getAbbreviation() : "");
+ sb.append("\t").append((this.asName != null ? this.asName : ""));
return sb.toString();
}
}
diff --git a/src/main/java/org/torproject/onionoo/docs/SummaryDocument.java b/src/main/java/org/torproject/onionoo/docs/SummaryDocument.java
index 92ebe69..fc84ba6 100644
--- a/src/main/java/org/torproject/onionoo/docs/SummaryDocument.java
+++ b/src/main/java/org/torproject/onionoo/docs/SummaryDocument.java
@@ -190,6 +190,17 @@ public class SummaryDocument extends Document {
return this.asNumber;
}
+ @JsonProperty("an")
+ private String asName;
+
+ public void setAsName(String asName) {
+ this.asName = asName;
+ }
+
+ public String getAsName() {
+ return this.asName;
+ }
+
@JsonProperty("fs")
private String firstSeenMillis;
@@ -364,7 +375,7 @@ public class SummaryDocument extends Document {
public SummaryDocument(boolean isRelay, String nickname,
String fingerprint, List<String> addresses, long lastSeenMillis,
boolean running, SortedSet<String> relayFlags, long consensusWeight,
- String countryCode, long firstSeenMillis, String asNumber,
+ String countryCode, long firstSeenMillis, String asNumber, String asName,
String contact, SortedSet<String> familyFingerprints,
SortedSet<String> effectiveFamily, String version, String operatingSystem,
String hostName, List<String> verifiedHostNames,
@@ -380,6 +391,7 @@ public class SummaryDocument extends Document {
this.setCountryCode(countryCode);
this.setFirstSeenMillis(firstSeenMillis);
this.setAsNumber(asNumber);
+ this.setAsName(asName);
this.setContact(contact);
this.setFamilyFingerprints(familyFingerprints);
this.setEffectiveFamily(effectiveFamily);
diff --git a/src/main/java/org/torproject/onionoo/server/NodeIndex.java b/src/main/java/org/torproject/onionoo/server/NodeIndex.java
index ed9ec44..d8b983a 100644
--- a/src/main/java/org/torproject/onionoo/server/NodeIndex.java
+++ b/src/main/java/org/torproject/onionoo/server/NodeIndex.java
@@ -85,6 +85,16 @@ class NodeIndex {
return relaysByAsNumber;
}
+ private Map<String, Set<String>> relaysByAsName = null;
+
+ public void setRelaysByAsName(Map<String, Set<String>> relaysByAsName) {
+ this.relaysByAsName = relaysByAsName;
+ }
+
+ public Map<String, Set<String>> getRelaysByAsName() {
+ return relaysByAsName;
+ }
+
private Map<String, Set<String>> relaysByFlag = null;
public void setRelaysByFlag(Map<String, Set<String>> relaysByFlag) {
diff --git a/src/main/java/org/torproject/onionoo/server/NodeIndexer.java b/src/main/java/org/torproject/onionoo/server/NodeIndexer.java
index 1f1d279..5a2ea8d 100644
--- a/src/main/java/org/torproject/onionoo/server/NodeIndexer.java
+++ b/src/main/java/org/torproject/onionoo/server/NodeIndexer.java
@@ -151,6 +151,7 @@ public class NodeIndexer implements ServletContextListener, Runnable {
new HashMap<>();
Map<String, Set<String>> newRelaysByCountryCode = new HashMap<>();
Map<String, Set<String>> newRelaysByAsNumber = new HashMap<>();
+ Map<String, Set<String>> newRelaysByAsName = new HashMap<>();
Map<String, Set<String>> newRelaysByFlag = new HashMap<>();
Map<String, Set<String>> newBridgesByFlag = new HashMap<>();
Map<String, Set<String>> newRelaysByContact = new HashMap<>();
@@ -230,6 +231,12 @@ public class NodeIndexer implements ServletContextListener, Runnable {
}
newRelaysByAsNumber.get(asNumber).add(fingerprint);
newRelaysByAsNumber.get(asNumber).add(hashedFingerprint);
+ String asName = entry.getAsName();
+ if (!newRelaysByAsName.containsKey(asName)) {
+ newRelaysByAsName.put(asName, new HashSet<>());
+ }
+ newRelaysByAsName.get(asName).add(fingerprint);
+ newRelaysByAsName.get(asName).add(hashedFingerprint);
for (String flag : entry.getRelayFlags()) {
String flagLowerCase = flag.toLowerCase();
if (!newRelaysByFlag.containsKey(flagLowerCase)) {
@@ -402,6 +409,7 @@ public class NodeIndexer implements ServletContextListener, Runnable {
newBridgeFingerprintSummaryLines);
newNodeIndex.setRelaysByCountryCode(newRelaysByCountryCode);
newNodeIndex.setRelaysByAsNumber(newRelaysByAsNumber);
+ newNodeIndex.setRelaysByAsName(newRelaysByAsName);
newNodeIndex.setRelaysByFlag(newRelaysByFlag);
newNodeIndex.setBridgesByFlag(newBridgesByFlag);
newNodeIndex.setRelaysByContact(newRelaysByContact);
diff --git a/src/main/java/org/torproject/onionoo/server/RequestHandler.java b/src/main/java/org/torproject/onionoo/server/RequestHandler.java
index 344178b..e401ae9 100644
--- a/src/main/java/org/torproject/onionoo/server/RequestHandler.java
+++ b/src/main/java/org/torproject/onionoo/server/RequestHandler.java
@@ -78,6 +78,12 @@ public class RequestHandler {
this.as = as;
}
+ private String[] asName;
+
+ public void setAsName(String[] asName) {
+ this.asName = asName;
+ }
+
private String flag;
public void setFlag(String flag) {
@@ -177,6 +183,7 @@ public class RequestHandler {
this.filterByFingerprint();
this.filterByCountryCode();
this.filterByAsNumber();
+ this.filterByAsName();
this.filterByFlag();
this.filterNodesByFirstSeenDays();
this.filterNodesByLastSeenDays();
@@ -427,6 +434,28 @@ public class RequestHandler {
this.filteredBridges.clear();
}
+ private void filterByAsName() {
+ if (this.asName == null) {
+ /* Not filtering by AS name. */
+ return;
+ }
+ Set<String> removeRelays = new HashSet<>();
+ for (Map.Entry<String, Set<String>> e :
+ this.nodeIndex.getRelaysByAsName().entrySet()) {
+ String asName = e.getKey();
+ for (String asNamePart : this.asName) {
+ if (asName == null || !asName.contains(asNamePart.toLowerCase())) {
+ removeRelays.addAll(e.getValue());
+ break;
+ }
+ }
+ }
+ for (String fingerprint : removeRelays) {
+ this.filteredRelays.remove(fingerprint);
+ }
+ this.filteredBridges.clear();
+ }
+
private void filterByFlag() {
if (this.flag == null) {
/* Not filtering by relay flag. */
diff --git a/src/main/java/org/torproject/onionoo/server/ResourceServlet.java b/src/main/java/org/torproject/onionoo/server/ResourceServlet.java
index 534dc0c..cf480d3 100644
--- a/src/main/java/org/torproject/onionoo/server/ResourceServlet.java
+++ b/src/main/java/org/torproject/onionoo/server/ResourceServlet.java
@@ -67,9 +67,9 @@ public class ResourceServlet extends HttpServlet {
private static Set<String> knownParameters = new HashSet<>(
Arrays.asList("type", "running", "search", "lookup", "fingerprint",
- "country", "as", "flag", "first_seen_days", "last_seen_days",
- "contact", "order", "limit", "offset", "fields", "family", "version",
- "os", "host_name", "recommended_version"));
+ "country", "as", "as_name", "flag", "first_seen_days",
+ "last_seen_days", "contact", "order", "limit", "offset", "fields",
+ "family", "version", "os", "host_name", "recommended_version"));
private static Set<String> illegalSearchQualifiers =
new HashSet<>(Arrays.asList(("search,fingerprint,order,limit,"
@@ -246,6 +246,15 @@ public class ResourceServlet extends HttpServlet {
}
rh.setAs(asNumberParameter);
}
+ if (parameterMap.containsKey("as_name")) {
+ String[] asNameParameter = this.parseAsNameParameter(
+ parameterMap.get("as_name"));
+ if (null == asNameParameter) {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ rh.setAsName(asNameParameter);
+ }
if (parameterMap.containsKey("flag")) {
String flagParameter = this.parseFlagParameter(
parameterMap.get("flag"));
@@ -503,6 +512,16 @@ public class ResourceServlet extends HttpServlet {
return parameter;
}
+ private String[] parseAsNameParameter(String parameter) {
+ for (char c : parameter.toCharArray()) {
+ if (c < 32 || c >= 127) {
+ /* Only accept printable ASCII. */
+ return null;
+ }
+ }
+ return parameter.toLowerCase().split(" ");
+ }
+
private static Pattern flagPattern =
Pattern.compile("^[a-zA-Z0-9]{1,20}$");
diff --git a/src/main/java/org/torproject/onionoo/updater/NodeDetailsStatusUpdater.java b/src/main/java/org/torproject/onionoo/updater/NodeDetailsStatusUpdater.java
index 6d22aa2..baba85f 100644
--- a/src/main/java/org/torproject/onionoo/updater/NodeDetailsStatusUpdater.java
+++ b/src/main/java/org/torproject/onionoo/updater/NodeDetailsStatusUpdater.java
@@ -492,6 +492,7 @@ public class NodeDetailsStatusUpdater implements DescriptorListener,
nodeStatus.getDefaultPolicy());
updatedNodeStatus.setPortList(nodeStatus.getPortList());
updatedNodeStatus.setAsNumber(nodeStatus.getAsNumber());
+ updatedNodeStatus.setAsName(nodeStatus.getAsName());
updatedNodeStatus.setRecommendedVersion(
nodeStatus.getRecommendedVersion());
updatedNodeStatus.setVersion(nodeStatus.getVersion());
@@ -879,6 +880,9 @@ public class NodeDetailsStatusUpdater implements DescriptorListener,
detailsStatus.setAsName(lookupResult.getAsName());
nodeStatus.setCountryCode(lookupResult.getCountryCode());
nodeStatus.setAsNumber(lookupResult.getAsNumber());
+ if (null != lookupResult.getAsName()) {
+ nodeStatus.setAsName(lookupResult.getAsName().toLowerCase());
+ }
}
if (this.consensusWeightFractions.containsKey(fingerprint)) {
diff --git a/src/main/java/org/torproject/onionoo/writer/SummaryDocumentWriter.java b/src/main/java/org/torproject/onionoo/writer/SummaryDocumentWriter.java
index dc6eba8..2bcc102 100644
--- a/src/main/java/org/torproject/onionoo/writer/SummaryDocumentWriter.java
+++ b/src/main/java/org/torproject/onionoo/writer/SummaryDocumentWriter.java
@@ -87,6 +87,7 @@ public class SummaryDocumentWriter implements DocumentWriter {
String countryCode = nodeStatus.getCountryCode();
long firstSeenMillis = nodeStatus.getFirstSeenMillis();
String asNumber = nodeStatus.getAsNumber();
+ String asName = nodeStatus.getAsName();
String contact = nodeStatus.getContact();
SortedSet<String> declaredFamily = nodeStatus.getDeclaredFamily();
SortedSet<String> effectiveFamily = nodeStatus.getEffectiveFamily();
@@ -100,7 +101,7 @@ public class SummaryDocumentWriter implements DocumentWriter {
SummaryDocument summaryDocument = new SummaryDocument(isRelay,
nickname, fingerprint, addresses, lastSeenMillis, running,
relayFlags, consensusWeight, countryCode, firstSeenMillis,
- asNumber, contact, declaredFamily, effectiveFamily, version,
+ asNumber, asName, contact, declaredFamily, effectiveFamily, version,
operatingSystem, hostName, verifiedHostNames,
unverifiedHostNames, recommendedVersion);
if (this.documentStore.store(summaryDocument, fingerprint)) {
diff --git a/src/test/java/org/torproject/onionoo/docs/SummaryDocumentTest.java b/src/test/java/org/torproject/onionoo/docs/SummaryDocumentTest.java
index 405fff6..f81dc73 100644
--- a/src/test/java/org/torproject/onionoo/docs/SummaryDocumentTest.java
+++ b/src/test/java/org/torproject/onionoo/docs/SummaryDocumentTest.java
@@ -21,6 +21,7 @@ public class SummaryDocumentTest {
false, new TreeSet<>(Arrays.asList(new String[] { "Running",
"Valid" })), 20L, "de",
DateTimeHelper.parse("2013-04-18 05:00:00"), "AS8767",
+ "m-net telekommunikations gmbh",
"torkaz <klaus dot zufall at gmx dot de> "
+ "<fb-token:np5_g_83jmf=>", new TreeSet<>(Arrays.asList(
new String[] { "001C13B3A55A71B977CA65EC85539D79C653A3FC",
diff --git a/src/test/java/org/torproject/onionoo/server/ResourceServletTest.java b/src/test/java/org/torproject/onionoo/server/ResourceServletTest.java
index 8100c00..37f7923 100644
--- a/src/test/java/org/torproject/onionoo/server/ResourceServletTest.java
+++ b/src/test/java/org/torproject/onionoo/server/ResourceServletTest.java
@@ -140,6 +140,7 @@ public class ResourceServletTest {
false, new TreeSet<>(Arrays.asList(new String[] { "Running",
"Valid" })), 20L, "de",
DateTimeHelper.parse("2013-04-18 05:00:00"), "AS8767",
+ "m-net telekommunikations gmbh",
"torkaz <klaus dot zufall at gmx dot de> "
+ "<fb-token:np5_g_83jmf=>", new TreeSet<>(Arrays.asList(
new String[] { "001C13B3A55A71B977CA65EC85539D79C653A3FC",
@@ -159,7 +160,8 @@ public class ResourceServletTest {
DateTimeHelper.parse("2013-04-24 12:00:00"), true,
new TreeSet<>(Arrays.asList(new String[] { "Fast", "Named",
"Running", "V2Dir", "Valid" })), 1140L, "us",
- DateTimeHelper.parse("2013-04-16 18:00:00"), "AS7922", null,
+ DateTimeHelper.parse("2013-04-16 18:00:00"), "AS7922",
+ "comcast cable communications, llc", null,
new TreeSet<String>(Arrays.asList(new String[] {
"000C5F55BD4814B917CC474BD537F1A3B33CCE2A" })),
new TreeSet<>(Arrays.asList(new String[] {
@@ -178,6 +180,7 @@ public class ResourceServletTest {
new TreeSet<>(Arrays.asList(new String[] { "Fast",
"Running", "Unnamed", "V2Dir", "Valid" })), 63L, "a1",
DateTimeHelper.parse("2013-04-16 18:00:00"), "AS6830",
+ "liberty global operations b.v.",
"1024d/51e2a1c7 \"steven j. murdoch\" "
+ "<tor+steven.murdoch(a)cl.cam.ac.uk> <fb-token:5sr_k_zs2wm=>",
new TreeSet<String>(), new TreeSet<String>(), "0.2.3.24-rc-dev",
@@ -191,7 +194,7 @@ public class ResourceServletTest {
Arrays.asList(new String[] { "10.199.7.176" }),
DateTimeHelper.parse("2013-04-21 18:07:03"), false,
new TreeSet<>(Arrays.asList(new String[] { "Valid" })), -1L,
- null, DateTimeHelper.parse("2013-04-20 15:37:04"), null, null,
+ null, DateTimeHelper.parse("2013-04-20 15:37:04"), null, null, null,
null, null, "0.2.2.39", null, null, null, null, true);
this.bridges.put("0000831B236DFF73D409AD17B40E2A728A53994F",
bridgeec2bridgercc7f31fe);
@@ -201,7 +204,7 @@ public class ResourceServletTest {
new String[] { "10.0.52.84" }),
DateTimeHelper.parse("2013-04-20 17:37:04"), false,
new TreeSet<>(Arrays.asList(new String[] { "Valid" })), -1L,
- null, DateTimeHelper.parse("2013-04-14 07:07:05"), null, null,
+ null, DateTimeHelper.parse("2013-04-14 07:07:05"), null, null, null,
null, null, null, null, null, null, null, null);
this.bridges.put("0002D9BDBBC230BD9C78FF502A16E0033EF87E0C",
bridgeUnnamed);
@@ -212,7 +215,7 @@ public class ResourceServletTest {
DateTimeHelper.parse("2013-04-24 01:07:04"), true,
new TreeSet<>(Arrays.asList(new String[] { "Running",
"Valid" })), -1L, null,
- DateTimeHelper.parse("2013-01-16 21:07:04"), null, null, null,
+ DateTimeHelper.parse("2013-01-16 21:07:04"), null, null, null, null,
null, "0.2.4.4-alpha-dev", "windows 7", null, null, null, false);
this.bridges.put("1FEDE50ED8DBA1DD9F9165F78C8131E4A44AB756",
bridgegummy);
@@ -1171,6 +1174,30 @@ public class ResourceServletTest {
}
@Test(timeout = 100)
+ public void testAsNameComcast() {
+ this.assertSummaryDocument("/summary?as_name=Comcast", 1, null, 0, null);
+ }
+
+ @Test(timeout = 100)
+ public void testAsNameComcastCable() {
+ this.assertSummaryDocument("/summary?as_name=Comcast Cable",
+ 1, null, 0, null);
+ }
+
+ @Test(timeout = 100)
+ public void testAsNameCableComcast() {
+ this.assertSummaryDocument("/summary?as_name=Cable Comcast",
+ 1, null, 0, null);
+ }
+
+ @Test(timeout = 100)
+ public void testAsNameMit() {
+ this.assertSummaryDocument(
+ "/summary?as_name=Massachusetts Institute of Technology",
+ 0, null, 0, null);
+ }
+
+ @Test(timeout = 100)
public void testFlagRunning() {
this.assertSummaryDocument(
"/summary?flag=Running", 3, null, 1, null);
diff --git a/src/test/java/org/torproject/onionoo/server/SummaryDocumentComparatorTest.java b/src/test/java/org/torproject/onionoo/server/SummaryDocumentComparatorTest.java
index 2b67206..c79565a 100644
--- a/src/test/java/org/torproject/onionoo/server/SummaryDocumentComparatorTest.java
+++ b/src/test/java/org/torproject/onionoo/server/SummaryDocumentComparatorTest.java
@@ -35,6 +35,7 @@ public class SummaryDocumentComparatorTest {
false, new TreeSet<>(Arrays.asList(new String[] { "Running",
"Valid" })), 20L, "de",
DateTimeHelper.parse("2013-04-18 05:00:00"), "AS8767",
+ "m-net telekommunikations gmbh",
"torkaz <klaus dot zufall at gmx dot de> "
+ "<fb-token:np5_g_83jmf=>", new TreeSet<>(Arrays.asList(
new String[] { "001C13B3A55A71B977CA65EC85539D79C653A3FC",