Use a single NetLayer instance for all connections.

This commit is contained in:
akwizgran
2012-02-07 09:58:13 +00:00
parent 9acaccb557
commit e8660c13ca
2 changed files with 65 additions and 26 deletions

View File

@@ -17,6 +17,7 @@ import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
import net.sf.briar.api.protocol.TransportId; import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.util.StringUtils; import net.sf.briar.util.StringUtils;
import org.silvertunnel.netlib.api.NetAddress;
import org.silvertunnel.netlib.api.NetFactory; import org.silvertunnel.netlib.api.NetFactory;
import org.silvertunnel.netlib.api.NetLayer; import org.silvertunnel.netlib.api.NetLayer;
import org.silvertunnel.netlib.api.NetLayerIDs; import org.silvertunnel.netlib.api.NetLayerIDs;
@@ -43,9 +44,9 @@ class TorPlugin implements DuplexPlugin {
private final DuplexPluginCallback callback; private final DuplexPluginCallback callback;
private final long pollingInterval; private final long pollingInterval;
private boolean running = false; // Locking: this private boolean running = false, connected = false; // Locking: this
private NetServerSocket socket = null; // Locking: this
private NetLayer netLayer = null; // Locking: this private NetLayer netLayer = null; // Locking: this
private NetServerSocket socket = null; // Locking: this
TorPlugin(@PluginExecutor Executor pluginExecutor, TorPlugin(@PluginExecutor Executor pluginExecutor,
DuplexPluginCallback callback, long pollingInterval) { DuplexPluginCallback callback, long pollingInterval) {
@@ -72,18 +73,18 @@ class TorPlugin implements DuplexPlugin {
private void bind() { private void bind() {
// Retrieve the hidden service address, or create one if necessary // Retrieve the hidden service address, or create one if necessary
TorHiddenServicePrivateNetAddress addr; TorHiddenServicePrivateNetAddress addr;
TorNetLayerUtil util = TorNetLayerUtil.getInstance();
TransportConfig c = callback.getConfig(); TransportConfig c = callback.getConfig();
String privateKey = c.get("privateKey"); String privateKey = c.get("privateKey");
if(privateKey == null) { if(privateKey == null) {
addr = createHiddenServiceAddress(c); addr = createHiddenServiceAddress(util, c);
} else { } else {
TorNetLayerUtil util = TorNetLayerUtil.getInstance();
try { try {
addr = util.parseTorHiddenServicePrivateNetAddressFromStrings( addr = util.parseTorHiddenServicePrivateNetAddressFromStrings(
privateKey, "", false); privateKey, "", false);
} catch(IOException e) { } catch(IOException e) {
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString()); if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
addr = createHiddenServiceAddress(c); addr = createHiddenServiceAddress(util, c);
} }
} }
TorHiddenServicePortPrivateNetAddress addrPort = TorHiddenServicePortPrivateNetAddress addrPort =
@@ -92,6 +93,15 @@ class TorPlugin implements DuplexPlugin {
NetFactory netFactory = NetFactory.getInstance(); NetFactory netFactory = NetFactory.getInstance();
NetLayer nl = netFactory.getNetLayerById(NetLayerIDs.TOR); NetLayer nl = netFactory.getNetLayerById(NetLayerIDs.TOR);
nl.waitUntilReady(); nl.waitUntilReady();
synchronized(this) {
if(!running) {
tryToClear(nl);
return;
}
netLayer = nl;
connected = true;
notifyAll();
}
// Publish the hidden service // Publish the hidden service
NetServerSocket ss; NetServerSocket ss;
try { try {
@@ -106,7 +116,6 @@ class TorPlugin implements DuplexPlugin {
return; return;
} }
socket = ss; socket = ss;
netLayer = nl;
} }
String onion = addr.getPublicOnionHostname(); String onion = addr.getPublicOnionHostname();
if(LOG.isLoggable(Level.INFO)) LOG.info("Listening on " + onion); if(LOG.isLoggable(Level.INFO)) LOG.info("Listening on " + onion);
@@ -117,8 +126,7 @@ class TorPlugin implements DuplexPlugin {
} }
private TorHiddenServicePrivateNetAddress createHiddenServiceAddress( private TorHiddenServicePrivateNetAddress createHiddenServiceAddress(
TransportConfig c) { TorNetLayerUtil util, TransportConfig c) {
TorNetLayerUtil util = TorNetLayerUtil.getInstance();
TorHiddenServicePrivateNetAddress addr = TorHiddenServicePrivateNetAddress addr =
util.createNewTorHiddenServicePrivateNetAddress(); util.createNewTorHiddenServicePrivateNetAddress();
RSAKeyPair keyPair = addr.getKeyPair(); RSAKeyPair keyPair = addr.getKeyPair();
@@ -128,6 +136,14 @@ class TorPlugin implements DuplexPlugin {
return addr; return addr;
} }
private void tryToClear(NetLayer nl) {
try {
nl.clear();
} catch(IOException e) {
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
}
}
private void tryToClose(NetServerSocket ss) { private void tryToClose(NetServerSocket ss) {
try { try {
ss.close(); ss.close();
@@ -156,15 +172,17 @@ class TorPlugin implements DuplexPlugin {
} }
public synchronized void stop() throws IOException { public synchronized void stop() throws IOException {
running = false;
if(socket != null) {
tryToClose(socket);
socket = null;
}
if(netLayer != null) { if(netLayer != null) {
netLayer.clear(); netLayer.clear();
netLayer = null; netLayer = null;
} }
if(socket != null) {
tryToClose(socket);
socket = null;
}
running = false;
connected = false;
notifyAll();
} }
public boolean shouldPoll() { public boolean shouldPoll() {
@@ -201,19 +219,28 @@ class TorPlugin implements DuplexPlugin {
} }
public DuplexTransportConnection createConnection(ContactId c) { public DuplexTransportConnection createConnection(ContactId c) {
NetLayer nl;
synchronized(this) { synchronized(this) {
if(!running) return null; while(!connected) {
if(!running) return null;
try {
wait();
} catch(InterruptedException e) {
if(LOG.isLoggable(Level.INFO))
LOG.info("Interrupted while waiting to connect");
Thread.currentThread().interrupt();
return null;
}
}
nl = netLayer;
} }
TransportProperties p = callback.getRemoteProperties().get(c); TransportProperties p = callback.getRemoteProperties().get(c);
if(p == null) return null; if(p == null) return null;
String onion = p.get("onion"); String onion = p.get("onion");
if(onion == null) return null; if(onion == null) return null;
NetAddress addr = new TcpipNetAddress(onion, 80);
try { try {
TcpipNetAddress addr = new TcpipNetAddress(onion, 80); NetSocket s = nl.createNetSocket(null, null, addr);
NetFactory netFactory = NetFactory.getInstance();
NetLayer netLayer = netFactory.getNetLayerById(NetLayerIDs.TOR);
netLayer.waitUntilReady();
NetSocket s = netLayer.createNetSocket(null, null, addr);
return new TorTransportConnection(s); return new TorTransportConnection(s);
} catch(IOException e) { } catch(IOException e) {
if(LOG.isLoggable(Level.INFO)) LOG.info(e.toString()); if(LOG.isLoggable(Level.INFO)) LOG.info(e.toString());

View File

@@ -1,7 +1,9 @@
package net.sf.briar.plugins.tor; package net.sf.briar.plugins.tor;
import java.io.PrintStream;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Map; import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@@ -40,10 +42,20 @@ public class TorPluginTest extends BriarTestCase {
TorPlugin clientPlugin = new TorPlugin(e, clientCallback, 0L); TorPlugin clientPlugin = new TorPlugin(e, clientCallback, 0L);
clientPlugin.start(); clientPlugin.start();
// Connect to the server's hidden service // Connect to the server's hidden service
DuplexTransportConnection c = clientPlugin.createConnection(contactId); DuplexTransportConnection clientEnd =
assertNotNull(c); clientPlugin.createConnection(contactId);
c.dispose(false, false); assertNotNull(clientEnd);
assertEquals(1, serverCallback.incomingConnections); DuplexTransportConnection serverEnd = serverCallback.incomingConnection;
assertNotNull(serverEnd);
// 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);
// Stop the plugins // Stop the plugins
serverPlugin.stop(); serverPlugin.stop();
clientPlugin.stop(); clientPlugin.stop();
@@ -89,7 +101,7 @@ public class TorPluginTest extends BriarTestCase {
private TransportConfig config = new TransportConfig(); private TransportConfig config = new TransportConfig();
private TransportProperties local = new TransportProperties(); private TransportProperties local = new TransportProperties();
private volatile int incomingConnections = 0; private volatile DuplexTransportConnection incomingConnection = null;
public TransportConfig getConfig() { public TransportConfig getConfig() {
return config; return config;
@@ -108,8 +120,8 @@ public class TorPluginTest extends BriarTestCase {
} }
public void setLocalProperties(TransportProperties p) { public void setLocalProperties(TransportProperties p) {
latch.countDown();
local = p; local = p;
latch.countDown();
} }
public int showChoice(String[] options, String... message) { public int showChoice(String[] options, String... message) {
@@ -123,7 +135,7 @@ public class TorPluginTest extends BriarTestCase {
public void showMessage(String... message) {} public void showMessage(String... message) {}
public void incomingConnectionCreated(DuplexTransportConnection d) { public void incomingConnectionCreated(DuplexTransportConnection d) {
incomingConnections++; incomingConnection = d;
} }
public void outgoingConnectionCreated(ContactId c, public void outgoingConnectionCreated(ContactId c,