commit ee696b09f02ae59e7dccf8a5eb68ca484051040e Author: Karsten Loesing karsten.loesing@gmx.net Date: Mon May 1 20:38:55 2017 +0200
Add support for six new key-value pairs added by OnionPerf.
OnionPerf adds six new key-value pairs to the .tpf format that Torperf/CollecTor did not produce: ENDPOINTLOCAL, ENDPOINTPROXY, ENDPOINTREMOTE, HOSTNAMELOCAL, HOSTNAMEREMOTE, and SOURCEADDRESS.
We should add support for these keys to metrics-lib, so that we can start using their values.
Implements #22122. --- CHANGELOG.md | 1 + .../org/torproject/descriptor/TorperfResult.java | 62 ++++++++++++++++ .../descriptor/impl/TorperfResultImpl.java | 84 ++++++++++++++++++++++ .../descriptor/impl/TorperfResultImplTest.java | 42 +++++++++++ 4 files changed, 189 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cb2acd..da9cb37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ # Medium changes - Fix a bug where unrecognized lines in extra-info descriptors below crypto blocks were silently skipped. + - Add support for six new key-value pairs added by OnionPerf.
# Changes in version 1.6.0 - 2017-02-17 diff --git a/src/main/java/org/torproject/descriptor/TorperfResult.java b/src/main/java/org/torproject/descriptor/TorperfResult.java index 1f4e50c..1958ed2 100644 --- a/src/main/java/org/torproject/descriptor/TorperfResult.java +++ b/src/main/java/org/torproject/descriptor/TorperfResult.java @@ -211,5 +211,67 @@ public interface TorperfResult extends Descriptor { * @since 1.0.0 */ public int getUsedBy(); + + /** + * Return the hostname, IP address, and port that the TGen client used to + * connect to the local tor SOCKS port, formatted as + * <code>hostname:ip:port</code>, which may be <code>"NULL:0.0.0.0:0"</code> + * if TGen was not able to find this information or <code>null</code> if the + * OnionPerf line didn't contain this information. + * + * @since 1.7.0 + */ + public String getEndpointLocal(); + + /** + * Return the hostname, IP address, and port that the TGen client used to + * connect to the SOCKS proxy server that tor runs, formatted as + * <code>hostname:ip:port</code>, which may be <code>"NULL:0.0.0.0:0"</code> + * if TGen was not able to find this information or <code>null</code> if the + * OnionPerf line didn't contain this information. + * + * @since 1.7.0 + */ + public String getEndpointProxy(); + + /** + * Return the hostname, IP address, and port that the TGen client used to + * connect to the remote server, formatted as <code>hostname:ip:port</code>, + * which may be <code>"NULL:0.0.0.0:0"</code> if TGen was not able to find + * this information or <code>null</code> if the OnionPerf line didn't contain + * this information. + * + * @since 1.7.0 + */ + public String getEndpointRemote(); + + /** + * Return the client machine hostname, which may be <code>"(NULL)"</code> if + * the TGen client was not able to find this information or <code>null</code> + * if the OnionPerf line didn't contain this information. + * + * @since 1.7.0 + */ + public String getHostnameLocal(); + + /** + * Return the server machine hostname, which may be <code>"(NULL)"</code> if + * the TGen server was not able to find this information or <code>null</code> + * if the OnionPerf line didn't contain this information. + * + * @since 1.7.0 + */ + public String getHostnameRemote(); + + /** + * Return the public IP address of the OnionPerf host obtained by connecting + * to well-known servers and finding the IP address in the result, which may + * be <code>"unknown"</code> if OnionPerf was not able to find this + * information or <code>null</code> if the OnionPerf line didn't contain this + * information. + * + * @since 1.7.0 + */ + public String getSourceAddress(); }
diff --git a/src/main/java/org/torproject/descriptor/impl/TorperfResultImpl.java b/src/main/java/org/torproject/descriptor/impl/TorperfResultImpl.java index f5fe892..16274c7 100644 --- a/src/main/java/org/torproject/descriptor/impl/TorperfResultImpl.java +++ b/src/main/java/org/torproject/descriptor/impl/TorperfResultImpl.java @@ -147,6 +147,24 @@ public class TorperfResultImpl extends DescriptorImpl case "USED_BY": this.parseUsedBy(value, keyValue, line); break; + case "ENDPOINTLOCAL": + this.parseEndpointLocal(value, keyValue, line); + break; + case "ENDPOINTPROXY": + this.parseEndpointProxy(value, keyValue, line); + break; + case "ENDPOINTREMOTE": + this.parseEndpointRemote(value, keyValue, line); + break; + case "HOSTNAMELOCAL": + this.parseHostnameLocal(value, keyValue, line); + break; + case "HOSTNAMEREMOTE": + this.parseHostnameRemote(value, keyValue, line); + break; + case "SOURCEADDRESS": + this.parseSourceAddress(value, keyValue, line); + break; default: if (key.startsWith("DATAPERC")) { this.parseDataPercentile(value, keyValue, line); @@ -359,6 +377,30 @@ public class TorperfResultImpl extends DescriptorImpl this.usedBy = this.parseInt(value, keyValue, line); }
+ private void parseEndpointLocal(String value, String keyValue, String line) { + this.endpointLocal = value; + } + + private void parseEndpointProxy(String value, String keyValue, String line) { + this.endpointProxy = value; + } + + private void parseEndpointRemote(String value, String keyValue, String line) { + this.endpointRemote = value; + } + + private void parseHostnameLocal(String value, String keyValue, String line) { + this.hostnameLocal = value; + } + + private void parseHostnameRemote(String value, String keyValue, String line) { + this.hostnameRemote = value; + } + + private void parseSourceAddress(String value, String keyValue, String line) { + this.sourceAddress = value; + } + private long parseTimestamp(String value, String keyValue, String line) throws DescriptorParseException { long timestamp = -1L; @@ -570,5 +612,47 @@ public class TorperfResultImpl extends DescriptorImpl public int getUsedBy() { return this.usedBy; } + + private String endpointLocal; + + @Override + public String getEndpointLocal() { + return this.endpointLocal; + } + + private String endpointProxy; + + @Override + public String getEndpointProxy() { + return this.endpointProxy; + } + + private String endpointRemote; + + @Override + public String getEndpointRemote() { + return this.endpointRemote; + } + + private String hostnameLocal; + + @Override + public String getHostnameLocal() { + return this.hostnameLocal; + } + + private String hostnameRemote; + + @Override + public String getHostnameRemote() { + return this.hostnameRemote; + } + + private String sourceAddress; + + @Override + public String getSourceAddress() { + return this.sourceAddress; + } }
diff --git a/src/test/java/org/torproject/descriptor/impl/TorperfResultImplTest.java b/src/test/java/org/torproject/descriptor/impl/TorperfResultImplTest.java index 080d16d..640b8a3 100644 --- a/src/test/java/org/torproject/descriptor/impl/TorperfResultImplTest.java +++ b/src/test/java/org/torproject/descriptor/impl/TorperfResultImplTest.java @@ -5,8 +5,10 @@ package org.torproject.descriptor.impl;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull;
import org.torproject.descriptor.Descriptor; +import org.torproject.descriptor.DescriptorParseException;
import org.junit.Test;
@@ -95,5 +97,45 @@ public class TorperfResultImplTest { assertEquals("DATAPERMILLE", torperfResult.getUnrecognizedKeys().firstKey()); } + + private static final String input2 = + "BUILDTIMES=0.490000009537,0.610000133514,0.75 CIRC_ID=8522 " + + "CONNECT=1493397365.14 DATACOMPLETE=1493397368.13 " + + "DATAPERC0=1493397367.67 DATAPERC10=1493397367.81 " + + "DATAPERC100=1493397368.13 DATAPERC20=1493397367.87 " + + "DATAPERC30=1493397367.87 DATAPERC40=1493397367.90 " + + "DATAPERC50=1493397367.91 DATAPERC60=1493397367.97 " + + "DATAPERC70=1493397367.97 DATAPERC80=1493397367.99 " + + "DATAPERC90=1493397367.99 DATAREQUEST=1493397367.33 " + + "DATARESPONSE=1493397367.67 DIDTIMEOUT=0 " + + "ENDPOINTLOCAL=localhost:127.0.0.1:42436 " + + "ENDPOINTPROXY=localhost:127.0.0.1:52265 " + + "ENDPOINTREMOTE=4jocm7xwo4ltrvzp.onion:0.0.0.0:80 FILESIZE=51200 " + + "HOSTNAMELOCAL=op-us HOSTNAMEREMOTE=op-us LAUNCH=1493396168.1 " + + "NEGOTIATE=1493397365.14 " + + "PATH=$F69BED36177ED727706512BA6A97755025EEA0FB," + + "$91D23D8A539B83D2FB56AA67ECD4D75CC093AC55," + + "$4DD902046E7155BBE79C34EE6D53BF7408B98CE4 QUANTILE=0.8 " + + "READBYTES=51269 REQUEST=1493397365.14 RESPONSE=1493397367.32 " + + "SOCKET=1493397365.14 SOURCE=op-us SOURCEADDRESS=199.119.112.144 " + + "START=1493397365.14 TIMEOUT=1500 USED_AT=1493397368.14 " + + "USED_BY=17429 WRITEBYTES=54"; + + @Test() + public void testEndpointsHostnamesSourceAddress() + throws DescriptorParseException { + List<Descriptor> result = TorperfResultImpl.parseTorperfResults( + input2.getBytes(), true); + assertEquals(1, result.size()); + TorperfResultImpl torperfResult = (TorperfResultImpl) result.get(0); + assertNull(torperfResult.getUnrecognizedKeys()); + assertEquals("localhost:127.0.0.1:42436", torperfResult.getEndpointLocal()); + assertEquals("localhost:127.0.0.1:52265", torperfResult.getEndpointProxy()); + assertEquals("4jocm7xwo4ltrvzp.onion:0.0.0.0:80", + torperfResult.getEndpointRemote()); + assertEquals("op-us", torperfResult.getHostnameLocal()); + assertEquals("op-us", torperfResult.getHostnameRemote()); + assertEquals("199.119.112.144", torperfResult.getSourceAddress()); + } }