From d46813c8667997be63df95511164e7d1d1607309 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Tue, 18 Dec 2018 13:07:24 +0100 Subject: [PATCH] TorHiddenServiceStartupTime Metric available --- build.gradle | 3 + .../src/main/java/bisq/monitor/Monitor.java | 2 + .../metric/TorHiddenServiceStartupTime.java | 95 +++++++++++++++++++ monitor/src/main/resources/metrics.properties | 6 ++ .../TorHiddenServiceStartupTimeTests.java | 91 ++++++++++++++++++ 5 files changed, 197 insertions(+) create mode 100644 monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java create mode 100644 monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java diff --git a/build.gradle b/build.gradle index 7d2d24d968..f82d571123 100644 --- a/build.gradle +++ b/build.gradle @@ -330,6 +330,9 @@ configure(project(':monitor')) { compile('com.github.JesusMcCloud.netlayer:tor.native:0.6.2') { exclude(module: 'slf4j-api') } + compile('com.github.JesusMcCloud.netlayer:tor.external:0.6') { + exclude(module: 'slf4j-api') + } testCompile 'org.junit.jupiter:junit-jupiter-api:5.3.2' testCompile 'org.junit.jupiter:junit-jupiter-params:5.3.2' diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index fe3dfdec98..34a59d4636 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -29,6 +29,7 @@ import org.berndpruenster.netlayer.tor.Tor; import bisq.monitor.metric.TorStartupTime; import bisq.monitor.metric.Metric; import bisq.monitor.metric.TorRoundtripTime; +import bisq.monitor.metric.TorHiddenServiceStartupTime; import lombok.extern.slf4j.Slf4j; import sun.misc.Signal; @@ -64,6 +65,7 @@ public class Monitor { // assemble Metrics metrics.add(new TorStartupTime()); metrics.add(new TorRoundtripTime()); + metrics.add(new TorHiddenServiceStartupTime()); // configure Metrics Properties properties = getProperties(); diff --git a/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java b/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java new file mode 100644 index 0000000000..8c36f5e0a0 --- /dev/null +++ b/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java @@ -0,0 +1,95 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.monitor.metric; + +import java.io.File; +import java.io.IOException; + +import org.berndpruenster.netlayer.tor.HiddenServiceSocket; + +import lombok.extern.slf4j.Slf4j; + +/** + * A Metric to measure the startup time of a Tor Hidden Service on a already + * running Tor. + * + * @author Florian Reimair + */ +@Slf4j +public class TorHiddenServiceStartupTime extends Metric { + + private static final String SERVICE_PORT = "run.servicePort"; + private static final String LOCAL_PORT = "run.localPort"; + private final String hiddenServiceDirectory = "metric_" + getName(); + + public TorHiddenServiceStartupTime() throws IOException { + super(); + } + + /** + * synchronization helper. Required because directly closing the + * HiddenServiceSocket in its ReadyListener causes a deadlock + */ + private void await() { + synchronized (hiddenServiceDirectory) { + try { + hiddenServiceDirectory.wait(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + private void proceed() { + synchronized (hiddenServiceDirectory) { + hiddenServiceDirectory.notify(); + } + } + + @Override + protected void execute() { + // prepare settings. Fetch them everytime we run the Metric so we do not have to + // restart on a config update + int localPort = Integer.parseInt(configuration.getProperty(LOCAL_PORT, "9998")); + int servicePort = Integer.parseInt(configuration.getProperty(SERVICE_PORT, "9999")); + + // clear directory so we get a new onion address everytime + new File(hiddenServiceDirectory).delete(); + + log.debug("creating the hidden service"); + // start timer - we do not need System.nanoTime as we expect our result to be in + // the range of tenth of seconds. + long start = System.currentTimeMillis(); + + HiddenServiceSocket hiddenServiceSocket = new HiddenServiceSocket(localPort, hiddenServiceDirectory, + servicePort); + hiddenServiceSocket.addReadyListener(socket -> { + // stop the timer and report + report(System.currentTimeMillis() - start); + log.debug("the hidden service is ready"); + proceed(); + return null; + }); + + await(); + log.debug("going to unpublish the hidden service..."); + hiddenServiceSocket.close(); + log.debug("[going to unpublish the hidden service...] done"); + } +} diff --git a/monitor/src/main/resources/metrics.properties b/monitor/src/main/resources/metrics.properties index b1d711e6b6..1c584561de 100644 --- a/monitor/src/main/resources/metrics.properties +++ b/monitor/src/main/resources/metrics.properties @@ -18,5 +18,11 @@ TorRoundtripTime.run.sampleSize=3 # torproject.org hidden service TorRoundtripTime.run.hosts=http://expyuzz4wqqyqhjn.onion:80 +#TorHiddenServiceStartupTime Metric +TorHiddenServiceStartupTime.enabled=true +TorHiddenServiceStartupTime.run.interval=2 +TorHiddenServiceStartupTime.run.localPort=90501 +TorHiddenServiceStartupTime.run.servicePort=90511 + #Another Metric Another.run.interval=5 \ No newline at end of file diff --git a/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java new file mode 100644 index 0000000000..6535380cb5 --- /dev/null +++ b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java @@ -0,0 +1,91 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.monitor; + + +import java.io.File; +import java.io.IOException; +import java.util.Properties; + +import org.berndpruenster.netlayer.tor.NativeTor; +import org.berndpruenster.netlayer.tor.Tor; +import org.berndpruenster.netlayer.tor.TorCtlException; +import org.junit.Assert; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import bisq.monitor.metric.TorHiddenServiceStartupTime; + +public class TorHiddenServiceStartupTimeTests { + + private class Dut extends TorHiddenServiceStartupTime { + + private long result; + + public Dut() throws IOException { + super(); + } + + @Override + protected void report(long value) { + super.report(value); + + result = value; + } + + public long results() { + return result; + } + } + + private final static File torWorkingDirectory = new File(TorHiddenServiceStartupTimeTests.class.getSimpleName()); + + @BeforeAll + public static void setup() throws TorCtlException { + Tor.setDefault(new NativeTor(torWorkingDirectory)); + } + + @Test + public void run() throws Exception { + + // configure + Properties configuration = new Properties(); + configuration.put("Dut.enabled", "true"); + configuration.put("Dut.run.interval", "5"); + + Dut DUT = new Dut(); + DUT.configure(configuration); + + // start + DUT.start(); + + // give it some time and then stop + Thread.sleep(180 * 1000); + DUT.shutdown(); + + // observe results + Assert.assertTrue(DUT.results() > 0); + } + + @AfterAll + public static void cleanup() { + Tor.getDefault().shutdown(); + torWorkingDirectory.delete(); + } +}