diff --git a/briar-core/.classpath b/briar-core/.classpath
index 31f5549e7ab9dabbd126edae9bc285c9c0cb84d5..b2548c1c59f9fba3d7150c671de6101cbc838696 100644
--- a/briar-core/.classpath
+++ b/briar-core/.classpath
@@ -7,7 +7,6 @@
 	<classpathentry kind="lib" path="libs/jnotify-0.93.jar"/>
 	<classpathentry kind="lib" path="libs/jssc-0.9-briar.jar" sourcepath="libs/source/jssc-0.9-briar-source.jar"/>
 	<classpathentry kind="lib" path="libs/sc-light-jdk15on-1.47.0.3-SNAPSHOT.jar" sourcepath="libs/source/sc-light-jdk15on-1.47.0.3-SNAPSHOT-source.jar"/>
-	<classpathentry kind="lib" path="libs/scpkix-jdk15on-1.47.0.3-SNAPSHOT.jar" sourcepath="libs/source/scpkix-jdk15on-1.47.0.3-SNAPSHOT-source.jar"/>
 	<classpathentry kind="lib" path="libs/scprov-jdk15on-1.47.0.3-SNAPSHOT.jar" sourcepath="libs/source/scprov-jdk15on-1.47.0.3-SNAPSHOT-source.jar"/>
 	<classpathentry kind="lib" path="libs/weupnp-0.1.1.jar"/>
 	<classpathentry kind="lib" path="libs/bluecove-2.1.1-SNAPSHOT-briar.jar"/>
@@ -18,6 +17,5 @@
 	<classpathentry kind="lib" path="/briar-api/libs/guice-3.0-no_aop.jar"/>
 	<classpathentry kind="lib" path="libs/jna-3.5.2-SNAPSHOT.jar"/>
 	<classpathentry kind="lib" path="libs/platform-3.5.2-SNAPSHOT.jar"/>
-	<classpathentry kind="lib" path="libs/silvertunnel.org-netlib-0.15-briar.jar" sourcepath="libs/source/silvertunnel.org-netlib-0.15-briar-source.jar"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/briar-core/libs/scpkix-jdk15on-1.47.0.3-SNAPSHOT.jar b/briar-core/libs/scpkix-jdk15on-1.47.0.3-SNAPSHOT.jar
deleted file mode 100644
index c245aff65207eb9724b0bcbe9b7652bf116f705b..0000000000000000000000000000000000000000
Binary files a/briar-core/libs/scpkix-jdk15on-1.47.0.3-SNAPSHOT.jar and /dev/null differ
diff --git a/briar-core/libs/silvertunnel.org-netlib-0.15-briar.jar b/briar-core/libs/silvertunnel.org-netlib-0.15-briar.jar
deleted file mode 100644
index 3b4d6d3a6452c7cb6c721bebdc99b6fdb70f8610..0000000000000000000000000000000000000000
Binary files a/briar-core/libs/silvertunnel.org-netlib-0.15-briar.jar and /dev/null differ
diff --git a/briar-core/libs/source/scpkix-jdk15on-1.47.0.3-SNAPSHOT-source.jar b/briar-core/libs/source/scpkix-jdk15on-1.47.0.3-SNAPSHOT-source.jar
deleted file mode 100644
index 0dc93633805dca34bb444061d7d8c9168bf3d3a6..0000000000000000000000000000000000000000
Binary files a/briar-core/libs/source/scpkix-jdk15on-1.47.0.3-SNAPSHOT-source.jar and /dev/null differ
diff --git a/briar-core/libs/source/silvertunnel.org-netlib-0.15-briar-source.jar b/briar-core/libs/source/silvertunnel.org-netlib-0.15-briar-source.jar
deleted file mode 100644
index 83a2d0bd437ef31610880b56e762388c2f7d0620..0000000000000000000000000000000000000000
Binary files a/briar-core/libs/source/silvertunnel.org-netlib-0.15-briar-source.jar and /dev/null differ
diff --git a/briar-core/src/net/sf/briar/plugins/PluginsModule.java b/briar-core/src/net/sf/briar/plugins/PluginsModule.java
index fe31c6e7db61434efa77b0d4f7cf61e421bae37b..f6b18cf20b408a2a6f50f886016fc5dc0fa0d074 100644
--- a/briar-core/src/net/sf/briar/plugins/PluginsModule.java
+++ b/briar-core/src/net/sf/briar/plugins/PluginsModule.java
@@ -21,7 +21,6 @@ import net.sf.briar.plugins.file.RemovableDrivePluginFactory;
 import net.sf.briar.plugins.modem.ModemPluginFactory;
 import net.sf.briar.plugins.tcp.LanTcpPluginFactory;
 import net.sf.briar.plugins.tcp.WanTcpPluginFactory;
-import net.sf.briar.plugins.tor.TorPluginFactory;
 import net.sf.briar.util.OsUtils;
 import android.content.Context;
 
@@ -78,7 +77,6 @@ public class PluginsModule extends AbstractModule {
 		}
 		factories.add(new LanTcpPluginFactory(pluginExecutor));
 		factories.add(new WanTcpPluginFactory(pluginExecutor, shutdownManager));
-		factories.add(new TorPluginFactory(pluginExecutor));
 		return new DuplexPluginConfig() {
 			public Collection<DuplexPluginFactory> getFactories() {
 				return factories;
diff --git a/briar-core/src/net/sf/briar/plugins/tor/TorPlugin.java b/briar-core/src/net/sf/briar/plugins/tor/TorPlugin.java
deleted file mode 100644
index 860963cf99cf84268d66253093f39290e0b323ac..0000000000000000000000000000000000000000
--- a/briar-core/src/net/sf/briar/plugins/tor/TorPlugin.java
+++ /dev/null
@@ -1,296 +0,0 @@
-package net.sf.briar.plugins.tor;
-
-import static java.util.logging.Level.INFO;
-import static java.util.logging.Level.WARNING;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Map;
-import java.util.concurrent.Executor;
-import java.util.logging.Logger;
-
-import net.sf.briar.api.ContactId;
-import net.sf.briar.api.TransportConfig;
-import net.sf.briar.api.TransportProperties;
-import net.sf.briar.api.crypto.PseudoRandom;
-import net.sf.briar.api.messaging.TransportId;
-import net.sf.briar.api.plugins.PluginExecutor;
-import net.sf.briar.api.plugins.duplex.DuplexPlugin;
-import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
-import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
-import net.sf.briar.util.StringUtils;
-
-import org.silvertunnel.netlib.api.NetAddress;
-import org.silvertunnel.netlib.api.NetFactory;
-import org.silvertunnel.netlib.api.NetLayer;
-import org.silvertunnel.netlib.api.NetLayerIDs;
-import org.silvertunnel.netlib.api.NetServerSocket;
-import org.silvertunnel.netlib.api.NetSocket;
-import org.silvertunnel.netlib.api.util.TcpipNetAddress;
-import org.silvertunnel.netlib.layer.tor.TorHiddenServicePortPrivateNetAddress;
-import org.silvertunnel.netlib.layer.tor.TorHiddenServicePrivateNetAddress;
-import org.silvertunnel.netlib.layer.tor.TorNetLayerUtil;
-import org.silvertunnel.netlib.layer.tor.util.Encryption;
-import org.silvertunnel.netlib.layer.tor.util.RSAKeyPair;
-
-class TorPlugin implements DuplexPlugin {
-
-	static final byte[] TRANSPORT_ID =
-			StringUtils.fromHexString("f264721575cb7ee710772f35abeb3db4"
-					+ "a91f474e14de346be296c2efc99effdd"
-					+ "f35921e6ed87a25c201f044da4767981");
-	static final TransportId ID = new TransportId(TRANSPORT_ID);
-
-	private static final Logger LOG =
-			Logger.getLogger(TorPlugin.class.getName());
-
-	private final Executor pluginExecutor;
-	private final DuplexPluginCallback callback;
-	private final long maxLatency, pollingInterval;
-
-	private boolean running = false, connected = false; // Locking: this
-	private NetLayer netLayer = null; // Locking: this
-	private NetServerSocket socket = null; // Locking: this
-
-	TorPlugin(@PluginExecutor Executor pluginExecutor,
-			DuplexPluginCallback callback, long maxLatency,
-			long pollingInterval) {
-		this.pluginExecutor = pluginExecutor;
-		this.callback = callback;
-		this.maxLatency = maxLatency;
-		this.pollingInterval = pollingInterval;
-	}
-
-	public TransportId getId() {
-		return ID;
-	}
-
-	public String getName() {
-		return "TOR_PLUGIN_NAME";
-	}
-
-	public long getMaxLatency() {
-		return maxLatency;
-	}
-
-	public boolean start() {
-		synchronized(this) {
-			running = true;
-		}
-		pluginExecutor.execute(new Runnable() {
-			public void run() {
-				bind();
-			}
-		});
-		return true;
-	}
-
-	private void bind() {
-		// Connect to Tor
-		NetFactory netFactory = NetFactory.getInstance();
-		NetLayer nl = netFactory.getNetLayerById(NetLayerIDs.TOR);
-		if(LOG.isLoggable(INFO)) LOG.info("Waiting for net layer to be ready");
-		nl.waitUntilReady();
-		if(LOG.isLoggable(INFO)) LOG.info("Net layer is ready");
-		synchronized(this) {
-			if(!running) {
-				tryToClear(nl);
-				return;
-			}
-			netLayer = nl;
-			connected = true;
-			notifyAll();
-		}
-		// If we're configured not to create a hidden service, return
-		TransportConfig c = callback.getConfig();
-		String noHiddenService = c.get("noHiddenService");
-		if(!StringUtils.isNullOrEmpty(noHiddenService)) {
-			if(LOG.isLoggable(INFO)) LOG.info("Not creating hidden service");
-			TransportProperties p = new TransportProperties();
-			p.put("onion", null);
-			callback.mergeLocalProperties(p);
-			return;
-		}
-		// Retrieve the hidden service address, or create one if necessary
-		TorHiddenServicePrivateNetAddress addr;
-		TorNetLayerUtil util = TorNetLayerUtil.getInstance();
-		String privateKey = c.get("privateKey");
-		if(StringUtils.isNullOrEmpty(privateKey)) {
-			if(LOG.isLoggable(INFO))
-				LOG.info("Creating hidden service address");
-			addr = createHiddenServiceAddress(util);
-		} else {
-			if(LOG.isLoggable(INFO))
-				LOG.info("Parsing hidden service address");
-			try {
-				addr = util.parseTorHiddenServicePrivateNetAddressFromStrings(
-						privateKey, "", false);
-			} catch(IOException e) {
-				if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-				addr = createHiddenServiceAddress(util);
-			}
-		}
-		TorHiddenServicePortPrivateNetAddress addrPort =
-				new TorHiddenServicePortPrivateNetAddress(addr, 80);
-		// Publish the hidden service
-		NetServerSocket ss;
-		if(LOG.isLoggable(INFO)) LOG.info("Publishing hidden service");
-		try {
-			ss = nl.createNetServerSocket(null, addrPort);
-		} catch(IOException e) {
-			if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-			return;
-		}
-		synchronized(this) {
-			if(!running) {
-				tryToClose(ss);
-				return;
-			}
-			socket = ss;
-		}
-		String onion = addr.getPublicOnionHostname();
-		if(LOG.isLoggable(INFO)) LOG.info("Listening on " + onion);
-		TransportProperties p = callback.getLocalProperties();
-		p.put("onion", onion);
-		callback.mergeLocalProperties(p);
-		acceptContactConnections(ss);
-	}
-
-	private TorHiddenServicePrivateNetAddress createHiddenServiceAddress(
-			TorNetLayerUtil util) {
-		TorHiddenServicePrivateNetAddress addr =
-				util.createNewTorHiddenServicePrivateNetAddress();
-		RSAKeyPair keyPair = addr.getKeyPair();
-		String privateKey = Encryption.getPEMStringFromRSAKeyPair(keyPair);
-		TransportConfig c = new TransportConfig();
-		c.put("privateKey", privateKey);
-		callback.mergeConfig(c);
-		return addr;
-	}
-
-	private void tryToClear(NetLayer nl) {
-		try {
-			nl.clear();
-		} catch(IOException e) {
-			if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-		}
-	}
-
-	private void tryToClose(NetServerSocket ss) {
-		try {
-			ss.close();
-		} catch(IOException e) {
-			if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-		}
-	}
-
-	private void acceptContactConnections(NetServerSocket ss) {
-		while(true) {
-			NetSocket s;
-			try {
-				s = ss.accept();
-			} catch(IOException e) {
-				// This is expected when the socket is closed
-				if(LOG.isLoggable(INFO)) LOG.log(INFO, e.toString(), e);
-				tryToClose(ss);
-				return;
-			}
-			callback.incomingConnectionCreated(new TorTransportConnection(s,
-					maxLatency));
-			synchronized(this) {
-				if(!running) return;
-			}
-		}
-	}
-
-	public synchronized void stop() throws IOException {
-		if(netLayer != null) {
-			netLayer.clear();
-			netLayer = null;
-		}
-		if(socket != null) {
-			tryToClose(socket);
-			socket = null;
-		}
-		running = false;
-		connected = false;
-		notifyAll();
-	}
-
-	public boolean shouldPoll() {
-		return true;
-	}
-
-	public long getPollingInterval() {
-		return pollingInterval;
-	}
-
-	public void poll(Collection<ContactId> connected) {
-		synchronized(this) {
-			if(!running) return;
-		}
-		Map<ContactId, TransportProperties> remote =
-				callback.getRemoteProperties();
-		for(final ContactId c : remote.keySet()) {
-			if(connected.contains(c)) continue;
-			pluginExecutor.execute(new Runnable() {
-				public void run() {
-					connectAndCallBack(c);
-				}
-			});
-		}
-	}
-
-	private void connectAndCallBack(ContactId c) {
-		DuplexTransportConnection d = createConnection(c);
-		if(d != null) callback.outgoingConnectionCreated(c, d);
-	}
-
-	public boolean supportsInvitations() {
-		return false;
-	}
-
-	public DuplexTransportConnection createConnection(ContactId c) {
-		NetLayer nl;
-		synchronized(this) {
-			while(!connected) {
-				if(!running) return null;
-				if(LOG.isLoggable(INFO))
-					LOG.info("Waiting for net layer before connecting");
-				try {
-					wait();
-				} catch(InterruptedException e) {
-					if(LOG.isLoggable(INFO))
-						LOG.info("Interrupted while waiting to connect");
-					Thread.currentThread().interrupt();
-					return null;
-				}
-			}
-			nl = netLayer;
-		}
-		TransportProperties p = callback.getRemoteProperties().get(c);
-		if(p == null) return null;
-		String onion = p.get("onion");
-		if(StringUtils.isNullOrEmpty(onion)) return null;
-		NetAddress addr = new TcpipNetAddress(onion, 80);
-		try {
-			if(LOG.isLoggable(INFO)) LOG.info("Connecting to hidden service");
-			NetSocket s = nl.createNetSocket(null, null, addr);
-			if(LOG.isLoggable(INFO)) LOG.info("Connected to hidden service");
-			return new TorTransportConnection(s, maxLatency);
-		} catch(IOException e) {
-			if(LOG.isLoggable(INFO)) LOG.log(INFO, e.toString(), e);
-			return null;
-		}
-	}
-
-	public DuplexTransportConnection sendInvitation(PseudoRandom r,
-			long timeout) {
-		throw new UnsupportedOperationException();
-	}
-
-	public DuplexTransportConnection acceptInvitation(PseudoRandom r,
-			long timeout) {
-		throw new UnsupportedOperationException();
-	}
-}
diff --git a/briar-core/src/net/sf/briar/plugins/tor/TorPluginFactory.java b/briar-core/src/net/sf/briar/plugins/tor/TorPluginFactory.java
deleted file mode 100644
index 65800cff169d18c8d6fd529eefb0f5906cbf09e2..0000000000000000000000000000000000000000
--- a/briar-core/src/net/sf/briar/plugins/tor/TorPluginFactory.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package net.sf.briar.plugins.tor;
-
-import java.util.concurrent.Executor;
-
-import net.sf.briar.api.messaging.TransportId;
-import net.sf.briar.api.plugins.PluginExecutor;
-import net.sf.briar.api.plugins.duplex.DuplexPlugin;
-import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
-import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
-import net.sf.briar.util.StringUtils;
-
-public class TorPluginFactory implements DuplexPluginFactory {
-
-	private static final long MAX_LATENCY = 5 * 60 * 1000; // 5 minutes
-	private static final long POLLING_INTERVAL = 15 * 60 * 1000; // 15 minutes
-
-	private final Executor pluginExecutor;
-
-	public TorPluginFactory(@PluginExecutor Executor pluginExecutor) {
-		this.pluginExecutor = pluginExecutor;
-	}
-
-	public TransportId getId() {
-		return TorPlugin.ID;
-	}
-
-	public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
-		// This plugin is not enabled by default
-		String enabled = callback.getConfig().get("enabled");
-		if(StringUtils.isNullOrEmpty(enabled)) return null;
-		return new TorPlugin(pluginExecutor, callback, MAX_LATENCY,
-				POLLING_INTERVAL);
-	}
-}
diff --git a/briar-core/src/net/sf/briar/plugins/tor/TorTransportConnection.java b/briar-core/src/net/sf/briar/plugins/tor/TorTransportConnection.java
deleted file mode 100644
index de785e687a1bac234d0ff7646be709e598908eca..0000000000000000000000000000000000000000
--- a/briar-core/src/net/sf/briar/plugins/tor/TorTransportConnection.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package net.sf.briar.plugins.tor;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
-
-import org.silvertunnel.netlib.api.NetSocket;
-
-class TorTransportConnection implements DuplexTransportConnection {
-
-	private final NetSocket socket;
-	private final long maxLatency;
-
-	TorTransportConnection(NetSocket socket, long maxLatency) {
-		this.socket = socket;
-		this.maxLatency = maxLatency;
-	}
-
-	public long getMaxLatency() {
-		return maxLatency;
-	}
-
-	public InputStream getInputStream() throws IOException {
-		return socket.getInputStream();
-	}
-
-	public OutputStream getOutputStream() throws IOException {
-		return socket.getOutputStream();
-	}
-
-	public boolean shouldFlush() {
-		return true;
-	}
-
-	public void dispose(boolean exception, boolean recognised)
-			throws IOException {
-		socket.close();
-	}
-}
diff --git a/briar-tests/build.xml b/briar-tests/build.xml
index 45b174c2a8d401d20c7dff8f84e5a2243d0c4679..a6e8c05845ae4560f84d66ebcbbf0375d41c9d25 100644
--- a/briar-tests/build.xml
+++ b/briar-tests/build.xml
@@ -126,7 +126,6 @@
 			</classpath>
 			<jvmarg value='-Djava.library.path=../briar-core/libs'/>
 			<test name='net.sf.briar.db.H2DatabaseTest'/>
-			<test name='net.sf.briar.plugins.tor.TorPluginTest'/>
 		</junit>
 	</target>
 </project>
diff --git a/briar-tests/src/net/sf/briar/plugins/tor/TorPluginTest.java b/briar-tests/src/net/sf/briar/plugins/tor/TorPluginTest.java
deleted file mode 100644
index 71b7e87bb0e1c66f48190a42ebd14594c4bc9d43..0000000000000000000000000000000000000000
--- a/briar-tests/src/net/sf/briar/plugins/tor/TorPluginTest.java
+++ /dev/null
@@ -1,175 +0,0 @@
-package net.sf.briar.plugins.tor;
-
-import static java.util.concurrent.TimeUnit.SECONDS;
-
-import java.io.PrintStream;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Scanner;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-
-import net.sf.briar.BriarTestCase;
-import net.sf.briar.api.ContactId;
-import net.sf.briar.api.TransportConfig;
-import net.sf.briar.api.TransportProperties;
-import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
-import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
-
-import org.junit.Test;
-
-public class TorPluginTest extends BriarTestCase {
-
-	private final ContactId contactId = new ContactId(234);
-
-	@Test
-	public void testHiddenService() throws Exception {
-		System.err.println("======== testHiddenService ========");
-		Executor e = Executors.newCachedThreadPool();
-		TorPlugin serverPlugin = null, clientPlugin = null;
-		try {
-			// Create a plugin instance for the server
-			Callback serverCallback = new Callback();
-			serverPlugin = new TorPlugin(e, serverCallback, 0, 0);
-			System.out.println("Starting server plugin");
-			serverPlugin.start();
-			// The plugin should create a hidden service... eventually
-			assertTrue(serverCallback.latch.await(600, SECONDS));
-			System.out.println("Started server plugin");
-			String onion = serverCallback.local.get("onion");
-			assertNotNull(onion);
-			assertTrue(onion.endsWith(".onion"));
-			// Create another plugin instance for the client
-			Callback clientCallback = new Callback();
-			clientCallback.config.put("noHiddenService", "true");
-			TransportProperties p = new TransportProperties();
-			p.put("onion", onion);
-			clientCallback.remote.put(contactId, p);
-			clientPlugin = new TorPlugin(e, clientCallback, 0, 0);
-			System.out.println("Starting client plugin");
-			clientPlugin.start();
-			// The plugin should start without creating a hidden service
-			assertTrue(clientCallback.latch.await(600, SECONDS));
-			System.out.println("Started client plugin");
-			// Connect to the server's hidden service
-			System.out.println("Connecting to hidden service");
-			DuplexTransportConnection clientEnd =
-					clientPlugin.createConnection(contactId);
-			assertNotNull(clientEnd);
-			DuplexTransportConnection serverEnd =
-					serverCallback.incomingConnection;
-			assertNotNull(serverEnd);
-			System.out.println("Connected to hidden service");
-			// Send some data through the Tor connection
-			PrintStream out = new PrintStream(clientEnd.getOutputStream());
-			out.println("Hello world");
-			out.flush();
-			Scanner in = new Scanner(serverEnd.getInputStream());
-			assertTrue(in.hasNextLine());
-			assertEquals("Hello world", in.nextLine());
-			serverEnd.dispose(false, false);
-			clientEnd.dispose(false, false);
-		} finally {
-			// Stop the plugins
-			System.out.println("Stopping plugins");
-			if(serverPlugin != null) serverPlugin.stop();
-			if(clientPlugin != null) clientPlugin.stop();
-			System.out.println("Stopped plugins");
-		}
-	}
-
-	@Test
-	public void testStoreAndRetrievePrivateKey() throws Exception {
-		System.err.println("======== testStoreAndRetrievePrivateKey ========");
-		Executor e = Executors.newCachedThreadPool();
-		TorPlugin plugin = null;
-		try {
-			// Start a plugin instance with no private key
-			Callback callback = new Callback();
-			plugin = new TorPlugin(e, callback, 0, 0);
-			System.out.println("Starting plugin without private key");
-			plugin.start();
-			// The plugin should create a hidden service... eventually
-			assertTrue(callback.latch.await(600, SECONDS));
-			System.out.println("Started plugin");
-			String onion = callback.local.get("onion");
-			assertNotNull(onion);
-			assertTrue(onion.endsWith(".onion"));
-			// Get the PEM-encoded private key
-			String privateKey = callback.config.get("privateKey");
-			assertNotNull(privateKey);
-			// Stop the plugin
-			System.out.println("Stopping plugin");
-			plugin.stop();
-			System.out.println("Stopped plugin");
-			// Start another instance, reusing the private key
-			callback = new Callback();
-			callback.config.put("privateKey", privateKey);
-			plugin = new TorPlugin(e, callback, 0, 0);
-			System.out.println("Starting plugin with private key");
-			plugin.start();
-			// The plugin should create a hidden service... eventually
-			assertTrue(callback.latch.await(600, SECONDS));
-			System.out.println("Started plugin");
-			// The onion URL should be the same
-			assertEquals(onion, callback.local.get("onion"));
-			// The private key should be the same
-			assertEquals(privateKey, callback.config.get("privateKey"));
-		} finally {
-			// Stop the plugin
-			System.out.println("Stopping plugin");
-			if(plugin != null) plugin.stop();
-			System.out.println("Stopped plugin");
-		}
-	}
-
-	private static class Callback implements DuplexPluginCallback {
-
-		private final Map<ContactId, TransportProperties> remote =
-				new Hashtable<ContactId, TransportProperties>();
-		private final CountDownLatch latch = new CountDownLatch(1);
-		private final TransportConfig config = new TransportConfig();
-		private final TransportProperties local = new TransportProperties();
-
-		private volatile DuplexTransportConnection incomingConnection = null;
-
-		public TransportConfig getConfig() {
-			return config;
-		}
-
-		public TransportProperties getLocalProperties() {
-			return local;
-		}
-
-		public Map<ContactId, TransportProperties> getRemoteProperties() {
-			return remote;
-		}
-
-		public void mergeConfig(TransportConfig c) {
-			config.putAll(c);
-		}
-
-		public void mergeLocalProperties(TransportProperties p) {
-			local.putAll(p);
-			latch.countDown();
-		}
-
-		public int showChoice(String[] options, String... message) {
-			return -1;
-		}
-
-		public boolean showConfirmationMessage(String... message) {
-			return false;
-		}
-
-		public void showMessage(String... message) {}
-
-		public void incomingConnectionCreated(DuplexTransportConnection d) {
-			incomingConnection = d;
-		}
-
-		public void outgoingConnectionCreated(ContactId c,
-				DuplexTransportConnection d) {}
-	}
-}