From e5620f8b05fa0ed7097e7e37fe356ad4b91d70f9 Mon Sep 17 00:00:00 2001 From: akwizgran <akwizgran@users.sourceforge.net> Date: Fri, 3 Oct 2014 13:29:12 +0100 Subject: [PATCH] Parts of our jtorctl patch have been merged upstream. --- briar-android/libs/jtorctl-briar.jar | Bin 16298 -> 15496 bytes .../briarproject/plugins/tor/TorPlugin.java | 25 +- jtorctl.patch | 1060 +---------------- 3 files changed, 8 insertions(+), 1077 deletions(-) diff --git a/briar-android/libs/jtorctl-briar.jar b/briar-android/libs/jtorctl-briar.jar index 1f90213fca321569b1bb89cb8b566c2dcc24be2f..f5753c6337180ddae63602370594f05745b3af22 100644 GIT binary patch delta 10540 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 delta 11299 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 diff --git a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java index f8c225e9ee..cdf700b85a 100644 --- a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java +++ b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java @@ -21,7 +21,6 @@ import java.net.Socket; import java.util.Arrays; import java.util.Collection; import java.util.List; -import java.util.Map; import java.util.Scanner; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; @@ -546,34 +545,14 @@ class TorPlugin implements DuplexPlugin, EventHandler { throw new UnsupportedOperationException(); } - public void circuitStatus(String status, String id, List<String> path, - Map<String, String> info) { - if(LOG.isLoggable(INFO)) { - String msg = "Circuit " + id + " " + status; - String purpose = info.get("PURPOSE"); - if(purpose != null) msg += ", purpose: " + purpose; - String hsState = info.get("HS_STATE"); - if(hsState != null) msg += ", state: " + hsState; - String rendQuery = info.get("REND_QUERY"); - if(rendQuery != null) msg += ", service: " + rendQuery; - if(!path.isEmpty()) msg += ", path: " + shortenPath(path); - LOG.info(msg); - } + public void circuitStatus(String status, String id, String path) { + if(LOG.isLoggable(INFO)) LOG.info("Circuit " + id + " " + status); if(status.equals("BUILT") && !circuitBuilt.getAndSet(true)) { LOG.info("First circuit built"); if(isRunning()) callback.pollNow(); } } - private String shortenPath(List<String> path) { - StringBuilder s = new StringBuilder(); - for(String id : path) { - if(s.length() > 0) s.append(','); - s.append(id.substring(1, 7)); - } - return s.toString(); - } - public void streamStatus(String status, String id, String target) {} public void orConnStatus(String status, String orName) { diff --git a/jtorctl.patch b/jtorctl.patch index 2375100a80..80fee4767a 100644 --- a/jtorctl.patch +++ b/jtorctl.patch @@ -1,1064 +1,16 @@ -diff -Bbur jtorctl/net/freehaven/tor/control/EventHandler.java jtorctl-briar/net/freehaven/tor/control/EventHandler.java ---- jtorctl/net/freehaven/tor/control/EventHandler.java 2014-04-02 11:26:56.000000000 +0100 -+++ jtorctl-briar/net/freehaven/tor/control/EventHandler.java 2014-05-14 16:54:29.291301601 +0100 -@@ -2,6 +2,9 @@ - // See LICENSE file for copying information - package net.freehaven.tor.control; - -+import java.util.List; -+import java.util.Map; -+ - /** - * Abstract interface whose methods are invoked when Tor sends us an event. - * -@@ -20,10 +23,21 @@ - * <li>"CLOSED" : circuit closed (was built)</li> - * </ul> - * -- * <b>circID</b> is the alphanumeric identifier of the affected circuit, -- * and <b>path</b> is a comma-separated list of alphanumeric ServerIDs. -+ * <b>circID</b> is the alphanumeric identifier of the affected circuit. -+ * <b>path</b> contains the alphanumeric ServerIDs of the circuit's routers. -+ * <b>info</b> may include some or all of the following entries: -+ * <ul> -+ * <li>BUILD_FLAGS: a comma-separated list of the circuit's build -+ * flags.</li> -+ * <li>PURPOSE: the purpose of the circuit.</li> -+ * <li>HS_STATE: the state of the circuit if it is a hidden service -+ * circuit.</li> -+ * <li>REND_QUERY: the hidden service address if the circuit is a -+ * hidden service circuit.</li> -+ * </ul> - */ -- public void circuitStatus(String status, String circID, String path); -+ public void circuitStatus(String status, String circID, List<String> path, -+ Map<String, String> info); - /** - * Invoked when a stream's status has changed. - * Possible values for <b>status</b> are: -diff -Bbur jtorctl/net/freehaven/tor/control/examples/DebuggingEventHandler.java jtorctl-briar/net/freehaven/tor/control/examples/DebuggingEventHandler.java ---- jtorctl/net/freehaven/tor/control/examples/DebuggingEventHandler.java 2014-04-02 11:26:56.000000000 +0100 -+++ jtorctl-briar/net/freehaven/tor/control/examples/DebuggingEventHandler.java 2014-04-02 11:31:48.000000000 +0100 -@@ -3,12 +3,12 @@ - package net.freehaven.tor.control.examples; - - import java.io.PrintWriter; --import java.util.Iterator; -+import java.util.List; - import net.freehaven.tor.control.EventHandler; - - public class DebuggingEventHandler implements EventHandler { - -- protected PrintWriter out; -+ private final PrintWriter out; - - public DebuggingEventHandler(PrintWriter p) { - out = p; -@@ -27,11 +30,13 @@ - out.println("Bandwidth usage: "+read+" bytes read; "+ - written+" bytes written."); - } -- public void newDescriptors(java.util.List<String> orList) { -+ -+ public void newDescriptors(List<String> orList) { - out.println("New descriptors for routers:"); -- for (Iterator<String> i = orList.iterator(); i.hasNext(); ) -- out.println(" "+i.next()); -+ for (String or : orList) -+ out.println(" "+or); - } -+ - public void message(String type, String msg) { - out.println("["+type+"] "+msg.trim()); - } -diff -Bbur jtorctl/net/freehaven/tor/control/examples/Main.java jtorctl-briar/net/freehaven/tor/control/examples/Main.java ---- jtorctl/net/freehaven/tor/control/examples/Main.java 2014-04-02 11:26:56.000000000 +0100 -+++ jtorctl-briar/net/freehaven/tor/control/examples/Main.java 2014-04-02 11:56:39.000000000 +0100 -@@ -2,14 +2,17 @@ - // See LICENSE file for copying information - package net.freehaven.tor.control.examples; - --import net.freehaven.tor.control.*; - import java.io.PrintWriter; -+import java.io.EOFException; - import java.io.IOException; -+import java.io.PrintWriter; -+import java.net.Socket; - import java.util.ArrayList; --import java.util.List; - import java.util.Arrays; -+import java.util.List; - import java.util.Map; --import java.util.Iterator; -+ -+import net.freehaven.tor.control.*; - - public class Main implements TorControlCommands { - -@@ -34,27 +37,22 @@ - } else { - System.err.println("Unrecognized command: "+args[0]); - } -- } catch (java.io.EOFException ex) { -+ } catch (EOFException ex) { - System.out.println("Control socket closed by Tor."); -+ } catch (TorControlError ex) { -+ System.err.println("Error from Tor process: "+ -+ ex+" ["+ex.getErrorMsg()+"]"); - } catch (IOException ex) { - System.err.println("IO exception when talking to Tor process: "+ - ex); - ex.printStackTrace(System.err); -- } catch (TorControlError ex) { -- System.err.println("Error from Tor process: "+ -- ex+" ["+ex.getErrorMsg()+"]"); - } - } - - private static TorControlConnection getConnection(String[] args, -- boolean daemon) -- throws IOException { -- TorControlConnection conn = TorControlConnection.getConnection( -- new java.net.Socket("127.0.0.1", 9100)); -- //if (conn instanceof TorControlConnection1) { -- // System.err.println("Debugging"); -- // ((TorControlConnection1)conn).setDebugging(System.err); -- //} -+ boolean daemon) throws IOException { -+ Socket s = new Socket("127.0.0.1", 9100); -+ TorControlConnection conn = new TorControlConnection(s); - conn.launchThread(daemon); - conn.authenticate(new byte[0]); - return conn; -@@ -87,9 +85,9 @@ - public static void getConfig(String[] args) throws IOException { - // Usage: get-config key key key - TorControlConnection conn = getConnection(args); -- List<ConfigEntry> lst = conn.getConf(Arrays.asList(args).subList(1,args.length)); -- for (Iterator<ConfigEntry> i = lst.iterator(); i.hasNext(); ) { -- ConfigEntry e = i.next(); -+ List<String> keys = Arrays.asList(args).subList(1, args.length); -+ List<ConfigEntry> lst = conn.getConf(keys); -+ for (ConfigEntry e : lst) { - System.out.println("KEY: "+e.key); - System.out.println("VAL: "+e.value); - } -@@ -97,9 +95,9 @@ - - public static void getInfo(String[] args) throws IOException { - TorControlConnection conn = getConnection(args); -- Map<String,String> m = conn.getInfo(Arrays.asList(args).subList(1,args.length)); -- for (Iterator<Map.Entry<String, String>> i = m.entrySet().iterator(); i.hasNext(); ) { -- Map.Entry<String,String> e = i.next(); -+ List<String> keys = Arrays.asList(args).subList(1, args.length); -+ Map<String,String> m = conn.getInfo(keys); -+ for (Map.Entry<String,String> e : m.entrySet()) { - System.out.println("KEY: "+e.getKey()); - System.out.println("VAL: "+e.getValue()); - } -@@ -108,10 +106,7 @@ - public static void listenForEvents(String[] args) throws IOException { - // Usage: listen [circ|stream|orconn|bw|newdesc|info|notice|warn|error]* - TorControlConnection conn = getConnection(args, false); -- ArrayList<String> lst = new ArrayList<String>(); -- for (int i = 1; i < args.length; ++i) { -- lst.add(args[i]); -- } -+ List<String> lst = Arrays.asList(args).subList(1, args.length); - conn.setEventHandler( - new DebuggingEventHandler(new PrintWriter(System.out, true))); - conn.setEvents(lst); -@@ -130,17 +125,13 @@ - } - - public static void authDemo(String[] args) throws IOException { -- - PasswordDigest pwd = PasswordDigest.generateDigest(); -- java.net.Socket s = new java.net.Socket("127.0.0.1", 9100); -- TorControlConnection conn = TorControlConnection.getConnection(s); -+ Socket s = new java.net.Socket("127.0.0.1", 9100); -+ TorControlConnection conn = new TorControlConnection(s); - conn.launchThread(true); - conn.authenticate(new byte[0]); -- - conn.setConf("HashedControlPassword", pwd.getHashedPassword()); -- -- conn = TorControlConnection.getConnection( -- new java.net.Socket("127.0.0.1", 9100)); -+ conn = new TorControlConnection(new Socket("127.0.0.1", 9100)); - conn.launchThread(true); - conn.authenticate(pwd.getSecret()); - } -diff -Bbur jtorctl/net/freehaven/tor/control/NullEventHandler.java jtorctl-briar/net/freehaven/tor/control/NullEventHandler.java ---- jtorctl/net/freehaven/tor/control/NullEventHandler.java 2014-04-02 11:26:56.000000000 +0100 -+++ jtorctl-briar/net/freehaven/tor/control/NullEventHandler.java 2014-05-14 16:54:43.219370671 +0100 -@@ -2,12 +2,16 @@ - // See LICENSE file for copying information - package net.freehaven.tor.control; - -+import java.util.List; -+import java.util.Map; -+ - /** - * Implementation of EventHandler that ignores all events. Useful - * when you only want to override one method. - */ - public class NullEventHandler implements EventHandler { -- public void circuitStatus(String status, String circID, String path) {} -+ public void circuitStatus(String status, String circID, List<String> path, -+ Map<String, String> info) {} - public void streamStatus(String status, String streamID, String target) {} - public void orConnStatus(String status, String orName) {} - public void bandwidthUsed(long read, long written) {} -diff -Bbur jtorctl/net/freehaven/tor/control/PasswordDigest.java jtorctl-briar/net/freehaven/tor/control/PasswordDigest.java ---- jtorctl/net/freehaven/tor/control/PasswordDigest.java 2014-04-02 11:26:56.000000000 +0100 -+++ jtorctl-briar/net/freehaven/tor/control/PasswordDigest.java 2014-04-02 12:29:20.000000000 +0100 -@@ -2,6 +2,7 @@ - // See LICENSE file for copying information - package net.freehaven.tor.control; - -+import java.security.NoSuchAlgorithmException; - import java.security.SecureRandom; - import java.security.MessageDigest; - -@@ -13,8 +14,8 @@ - */ - public class PasswordDigest { - -- byte[] secret; -- String hashedKey; -+ private final byte[] secret; -+ private final String hashedKey; - - /** Return a new password digest with a random secret and salt. */ - public static PasswordDigest generateDigest() { -@@ -41,7 +42,7 @@ - rng.nextBytes(specifier); - specifier[8] = 96; - } -- hashedKey = "16:"+encodeBytes(secretToKey(secret, specifier)); -+ hashedKey = "16:"+Bytes.hex(secretToKey(secret, specifier)); - } - - /** Return the secret used to generate this password hash. -@@ -63,7 +64,7 @@ - MessageDigest d; - try { - d = MessageDigest.getInstance("SHA-1"); -- } catch (java.security.NoSuchAlgorithmException ex) { -+ } catch (NoSuchAlgorithmException ex) { - throw new RuntimeException("Can't run without sha-1."); - } - int c = (specifier[8])&0xff; -@@ -86,12 +87,5 @@ - System.arraycopy(specifier, 0, key, 0, 9); - return key; - } -- -- /** Return a hexadecimal encoding of a byte array. */ -- // XXX There must be a better way to do this in Java. -- private static final String encodeBytes(byte[] ba) { -- return Bytes.hex(ba); -- } -- - } - diff -Bbur jtorctl/net/freehaven/tor/control/TorControlConnection.java jtorctl-briar/net/freehaven/tor/control/TorControlConnection.java ---- jtorctl/net/freehaven/tor/control/TorControlConnection.java 2014-04-02 11:26:56.000000000 +0100 -+++ jtorctl-briar/net/freehaven/tor/control/TorControlConnection.java 2014-05-14 16:59:18.428735366 +0100 -@@ -2,96 +2,94 @@ - // See LICENSE file for copying information - package net.freehaven.tor.control; - -+import java.io.BufferedReader; - import java.io.IOException; --import java.net.SocketException; -+import java.io.InputStream; -+import java.io.InputStreamReader; -+import java.io.OutputStream; -+import java.io.OutputStreamWriter; -+import java.io.PrintStream; -+import java.io.PrintWriter; -+import java.io.Reader; -+import java.io.Writer; -+import java.net.Socket; - import java.util.ArrayList; -+import java.util.Arrays; - import java.util.Collection; -+import java.util.Collections; - import java.util.HashMap; --import java.util.Iterator; - import java.util.LinkedList; - import java.util.List; - import java.util.Map; - import java.util.StringTokenizer; --import java.util.concurrent.CancellationException; - - /** A connection to a running Tor process as specified in control-spec.txt. */ --public class TorControlConnection implements TorControlCommands --{ -+public class TorControlConnection implements TorControlCommands { - -- protected EventHandler handler; -+ private final LinkedList<Waiter> waiters; -+ private final BufferedReader input; -+ private final Writer output; - -- protected LinkedList<Waiter> waiters; -+ private ControlParseThread thread; // Locking: this - -- protected ControlParseThread thread; -+ private volatile EventHandler handler; -+ private volatile PrintWriter debugOutput; -+ private volatile IOException parseThreadException; - -- protected java.io.BufferedReader input; -+ private static class Waiter { - -- protected java.io.Writer output; -- -- protected java.io.PrintWriter debugOutput; -- -- static class Waiter { - List<ReplyLine> response; -- public synchronized List<ReplyLine> getResponse() { -- try { -+ -+ synchronized List<ReplyLine> getResponse() throws InterruptedException { - while (response == null) { - wait(); - } -- } catch (InterruptedException ex) { -- throw new CancellationException( -- "Please don't interrupt library calls."); -- } - return response; - } -- public synchronized void setResponse(List<ReplyLine> response) { -+ -+ synchronized void setResponse(List<ReplyLine> response) { - this.response = response; - notifyAll(); - } - } - -- static class ReplyLine { -- public String status; -- public String msg; -- public String rest; -+ private static class ReplyLine { -+ -+ final String status; -+ final String msg; -+ final String rest; - - ReplyLine(String status, String msg, String rest) { -- this.status = status; this.msg = msg; this.rest = rest; -+ this.status = status; -+ this.msg = msg; -+ this.rest = rest; - } - } - -- public static TorControlConnection getConnection(java.net.Socket sock) -- throws IOException -- { -- return new TorControlConnection(sock); -- } -- - /** Create a new TorControlConnection to communicate with Tor over - * a given socket. After calling this constructor, it is typical to - * call launchThread and authenticate. */ -- public TorControlConnection(java.net.Socket connection) -- throws IOException { -- this(connection.getInputStream(), connection.getOutputStream()); -+ public TorControlConnection(Socket s) throws IOException { -+ this(s.getInputStream(), s.getOutputStream()); - } - - /** Create a new TorControlConnection to communicate with Tor over - * an arbitrary pair of data streams. - */ -- public TorControlConnection(java.io.InputStream i, java.io.OutputStream o) { -- this(new java.io.InputStreamReader(i), -- new java.io.OutputStreamWriter(o)); -+ public TorControlConnection(InputStream i, OutputStream o) { -+ this(new InputStreamReader(i), new OutputStreamWriter(o)); - } - -- public TorControlConnection(java.io.Reader i, java.io.Writer o) { -- this.output = o; -- if (i instanceof java.io.BufferedReader) -- this.input = (java.io.BufferedReader) i; -+ public TorControlConnection(Reader i, Writer o) { -+ if (i instanceof BufferedReader) -+ input = (BufferedReader) i; - else -- this.input = new java.io.BufferedReader(i); -- -- this.waiters = new LinkedList<Waiter>(); -+ input = new BufferedReader(i); -+ output = o; -+ waiters = new LinkedList<Waiter>(); - } - -- protected final void writeEscaped(String s) throws IOException { -+ private final void writeEscaped(String s) throws IOException { - StringTokenizer st = new StringTokenizer(s, "\n"); - while (st.hasMoreTokens()) { - String line = st.nextToken(); -@@ -110,12 +108,11 @@ - debugOutput.print(">> .\n"); - } - -- protected static final String quote(String s) { -- StringBuffer sb = new StringBuffer("\""); -+ private static final String quote(String s) { -+ StringBuilder sb = new StringBuilder("\""); - for (int i = 0; i < s.length(); ++i) { - char c = s.charAt(i); -- switch (c) -- { -+ switch (c) { - case '\r': - case '\n': - case '\\': -@@ -128,7 +125,7 @@ - return sb.toString(); - } - -- protected final ArrayList<ReplyLine> readReply() throws IOException { -+ private ArrayList<ReplyLine> readReply() throws IOException { - ArrayList<ReplyLine> reply = new ArrayList<ReplyLine>(); - char c; - do { -@@ -153,7 +150,7 @@ - String msg = line.substring(4); - String rest = null; - if (c == '+') { -- StringBuffer data = new StringBuffer(); -+ StringBuilder data = new StringBuilder(); - while (true) { - line = input.readLine(); - if (debugOutput != null) -@@ -172,8 +169,9 @@ - return reply; +--- jtorctl/net/freehaven/tor/control/TorControlConnection.java 2014-10-03 12:21:51.883098440 +0100 ++++ jtorctl-briar/net/freehaven/tor/control/TorControlConnection.java 2014-10-03 12:17:07.429687913 +0100 +@@ -728,5 +728,12 @@ + sendAndWaitForResponse("CLOSECIRCUIT "+circID+ + (ifUnused?" IFUNUSED":"")+"\r\n", null); } - -- protected synchronized List<ReplyLine> sendAndWaitForResponse(String s,String rest) -- throws IOException { -+ private synchronized List<ReplyLine> sendAndWaitForResponse(String s, -+ String rest) throws IOException { -+ if (parseThreadException != null) throw parseThreadException; - checkThread(); - Waiter w = new Waiter(); - if (debugOutput != null) -@@ -185,38 +183,58 @@ - output.flush(); - waiters.addLast(w); - } -- List<ReplyLine> lst = w.getResponse(); -- for (Iterator<ReplyLine> i = lst.iterator(); i.hasNext(); ) { -- ReplyLine c = i.next(); -- if (! c.status.startsWith("2")) -- throw new TorControlError("Error reply: "+c.msg); -+ List<ReplyLine> lst; -+ try { -+ lst = w.getResponse(); -+ } catch (InterruptedException ex) { -+ throw new IOException(ex.toString()); -+ } -+ for (ReplyLine line : lst) { -+ if (! line.status.startsWith("2")) -+ throw new TorControlError("Error reply: "+line.msg); - } - return lst; - } - - /** Helper: decode a CMD_EVENT command and dispatch it to our - * EventHandler (if any). */ -- protected void handleEvent(ArrayList<ReplyLine> events) { -+ private void handleEvent(ArrayList<ReplyLine> events) { - if (handler == null) - return; - -- for (Iterator<ReplyLine> i = events.iterator(); i.hasNext(); ) { -- ReplyLine line = i.next(); -+ for (ReplyLine line : events) { - int idx = line.msg.indexOf(' '); -+ if (idx == -1) -+ continue; - String tp = line.msg.substring(0, idx).toUpperCase(); - String rest = line.msg.substring(idx+1); - if (tp.equals("CIRC")) { - List<String> lst = Bytes.splitStr(null, rest); -- handler.circuitStatus(lst.get(1), -- lst.get(0), -- lst.get(1).equals("LAUNCHED") -- || lst.size() < 2 ? "" -- : lst.get(2)); -+ int size = lst.size(), firstKeyValue; -+ List<String> path; -+ if (size < 3 || lst.get(1).equals("LAUNCHED")) { -+ path = Collections.emptyList(); -+ firstKeyValue = 2; -+ } else { -+ path = Arrays.asList(lst.get(2).split(",")); -+ path = Collections.unmodifiableList(path); -+ firstKeyValue = 3; -+ } -+ Map<String, String> info = new HashMap<String, String>(); -+ for (int i = firstKeyValue; i < size; i++) { -+ String kv = lst.get(i); -+ idx = kv.indexOf('='); -+ if (idx >= 0) { -+ String key = kv.substring(0, idx); -+ String value = kv.substring(idx+1); -+ info.put(key, value); -+ } -+ } -+ info = Collections.unmodifiableMap(info); -+ handler.circuitStatus(lst.get(1), lst.get(0), path, info); - } else if (tp.equals("STREAM")) { - List<String> lst = Bytes.splitStr(null, rest); -- handler.streamStatus(lst.get(1), -- lst.get(0), -- lst.get(3)); -+ handler.streamStatus(lst.get(1), lst.get(0), lst.get(3)); - // XXXX circID. - } else if (tp.equals("ORCONN")) { - List<String> lst = Bytes.splitStr(null, rest); -@@ -240,23 +258,22 @@ - } - } - -- - /** Sets <b>w</b> as the PrintWriter for debugging output, - * which writes out all messages passed between Tor and the controller. -- * Outgoing messages are preceded by "\>\>" and incoming messages are preceded -- * by "\<\<" -+ * Outgoing messages are preceded by "\>\>" and incoming messages are -+ * preceded by "\<\<" - */ -- public void setDebugging(java.io.PrintWriter w) { -+ public void setDebugging(PrintWriter w) { - debugOutput = w; - } - - /** Sets <b>s</b> as the PrintStream for debugging output, - * which writes out all messages passed between Tor and the controller. -- * Outgoing messages are preceded by "\>\>" and incoming messages are preceded -- * by "\<\<" -+ * Outgoing messages are preceded by "\>\>" and incoming messages are -+ * preceded by "\<\<" - */ -- public void setDebugging(java.io.PrintStream s) { -- debugOutput = new java.io.PrintWriter(s, true); -+ public void setDebugging(PrintStream s) { -+ debugOutput = new PrintWriter(s, true); - } - - /** Set the EventHandler object that will be notified of any -@@ -271,50 +288,43 @@ - * This is necessary to handle asynchronous events and synchronous - * responses that arrive independantly over the same socket. - */ -- public Thread launchThread(boolean daemon) { -+ public synchronized Thread launchThread(boolean daemon) { - ControlParseThread th = new ControlParseThread(); - if (daemon) - th.setDaemon(true); - th.start(); -- this.thread = th; -+ thread = th; - return th; - } - -- protected class ControlParseThread extends Thread { -- boolean stopped = false; -+ private class ControlParseThread extends Thread { -+ - @Override - public void run() { - try { - react(); -- } catch (SocketException ex) { -- if (stopped) // we expected this exception -- return; -- throw new RuntimeException(ex); - } catch (IOException ex) { -- throw new RuntimeException(ex); -- } -+ parseThreadException = ex; - } -- public void stopListening() { -- this.stopped = true; - } - } - -- protected final void checkThread() { -+ private synchronized void checkThread() { - if (thread == null) - launchThread(true); - } - - /** helper: implement the main background loop. */ -- protected void react() throws IOException { -+ private void react() throws IOException { - while (true) { - ArrayList<ReplyLine> lst = readReply(); - if (lst.isEmpty()) { - // connection has been closed remotely! end the loop! - return; - } -- if ((lst.get(0)).status.startsWith("6")) -+ if ((lst.get(0)).status.startsWith("6")) { - handleEvent(lst); -- else { -+ } else { - Waiter w; - synchronized (waiters) { - w = waiters.removeFirst(); -@@ -324,20 +334,16 @@ - } - } - -- /** Change the value of the configuration option 'key' to 'val'. -- */ -+ /** Change the value of the configuration option 'key' to 'val'. */ - public void setConf(String key, String value) throws IOException { -- List<String> lst = new ArrayList<String>(); -- lst.add(key+" "+value); -- setConf(lst); -+ setConf(Arrays.asList(key+" "+value)); - } - - /** Change the values of the configuration options stored in kvMap. */ - public void setConf(Map<String, String> kvMap) throws IOException { - List<String> lst = new ArrayList<String>(); -- for (Iterator<Map.Entry<String,String>> it = kvMap.entrySet().iterator(); it.hasNext(); ) { -- Map.Entry<String,String> ent = it.next(); -- lst.add(ent.getKey()+" "+ent.getValue()+"\n"); -+ for (Map.Entry<String,String> e : kvMap.entrySet()) { -+ lst.add(e.getKey()+" "+e.getValue()+"\n"); - } - setConf(lst); - } -@@ -345,34 +351,33 @@ - /** Changes the values of the configuration options stored in - * <b>kvList</b>. Each list element in <b>kvList</b> is expected to be - * String of the format "key value". -- * -+ * <p> - * Tor behaves as though it had just read each of the key-value pairs - * from its configuration file. Keywords with no corresponding values have - * their configuration values reset to their defaults. setConf is - * all-or-nothing: if there is an error in any of the configuration settings, - * Tor sets none of them. -- * -+ * <p> - * When a configuration option takes multiple values, or when multiple - * configuration keys form a context-sensitive group (see getConf below), then - * setting any of the options in a setConf command is taken to reset all of - * the others. For example, if two ORBindAddress values are configured, and a - * command arrives containing a single ORBindAddress value, the new - * command's value replaces the two old values. -- * -+ * <p> - * To remove all settings for a given option entirely (and go back to its - * default value), include a String in <b>kvList</b> containing the key and no value. - */ - public void setConf(Collection<String> kvList) throws IOException { - if (kvList.size() == 0) - return; -- StringBuffer b = new StringBuffer("SETCONF"); -- for (Iterator<String> it = kvList.iterator(); it.hasNext(); ) { -- String kv = it.next(); -+ StringBuilder b = new StringBuilder("SETCONF"); -+ for (String kv : kvList) { - int i = kv.indexOf(' '); - if (i == -1) - b.append(" ").append(kv); -- b.append(" ").append(kv.substring(0,i)).append("=") -- .append(quote(kv.substring(i+1))); -+ b.append(" ").append(kv.substring(0,i)).append("="); -+ b.append(quote(kv.substring(i+1))); - } - b.append("\r\n"); - sendAndWaitForResponse(b.toString(), null); -@@ -384,9 +389,8 @@ - public void resetConf(Collection<String> keys) throws IOException { - if (keys.size() == 0) - return; -- StringBuffer b = new StringBuffer("RESETCONF"); -- for (Iterator<String> it = keys.iterator(); it.hasNext(); ) { -- String key = it.next(); -+ StringBuilder b = new StringBuilder("RESETCONF"); -+ for (String key : keys) { - b.append(" ").append(key); - } - b.append("\r\n"); -@@ -402,10 +406,10 @@ - - /** Requests the values of the configuration variables listed in <b>keys</b>. - * Results are returned as a list of ConfigEntry objects. -- * -+ * <p> - * If an option appears multiple times in the configuration, all of its - * key-value pairs are returned in order. -- * -+ * <p> - * Some options are context-sensitive, and depend on other options with - * different keywords. These cannot be fetched directly. Currently there - * is only one such option: clients should use the "HiddenServiceOptions" -@@ -413,61 +417,63 @@ - * HiddenServiceNodes, and HiddenServiceExcludeNodes option settings. - */ - public List<ConfigEntry> getConf(Collection<String> keys) throws IOException { -- StringBuffer sb = new StringBuffer("GETCONF"); -- for (Iterator<String> it = keys.iterator(); it.hasNext(); ) { -- String key = it.next(); -+ StringBuilder sb = new StringBuilder("GETCONF"); -+ for (String key : keys) { - sb.append(" ").append(key); - } - sb.append("\r\n"); - List<ReplyLine> lst = sendAndWaitForResponse(sb.toString(), null); - List<ConfigEntry> result = new ArrayList<ConfigEntry>(); -- for (Iterator<ReplyLine> it = lst.iterator(); it.hasNext(); ) { -- String kv = (it.next()).msg; -+ for (ReplyLine line : lst) { -+ String kv = line.msg; - int idx = kv.indexOf('='); -- if (idx >= 0) -- result.add(new ConfigEntry(kv.substring(0, idx), -- kv.substring(idx+1))); -- else -+ if (idx >= 0) { -+ String key = kv.substring(0, idx); -+ String value = kv.substring(idx+1); -+ result.add(new ConfigEntry(key, value)); -+ } else { - result.add(new ConfigEntry(kv)); - } -+ } - return result; - } - - /** Request that the server inform the client about interesting events. - * Each element of <b>events</b> is one of the following Strings: -- * ["CIRC" | "STREAM" | "ORCONN" | "BW" | "DEBUG" | -- * "INFO" | "NOTICE" | "WARN" | "ERR" | "NEWDESC" | "ADDRMAP"] . -- * -+ * ["CIRC" | "STREAM" | "ORCONN" | "BW" | "DEBUG" | "INFO" | "NOTICE" | -+ * "WARN" | "ERR" | "NEWDESC" | "ADDRMAP"] . -+ * <p> - * Any events not listed in the <b>events</b> are turned off; thus, calling - * setEvents with an empty <b>events</b> argument turns off all event reporting. - */ - public void setEvents(List<String> events) throws IOException { -- StringBuffer sb = new StringBuffer("SETEVENTS"); -- for (Iterator<String> it = events.iterator(); it.hasNext(); ) { -- sb.append(" ").append(it.next()); -+ StringBuilder sb = new StringBuilder("SETEVENTS"); -+ for (String event : events) { -+ sb.append(" ").append(event); - } - sb.append("\r\n"); - sendAndWaitForResponse(sb.toString(), null); - } - - /** Authenticates the controller to the Tor server. -- * -+ * <p> - * By default, the current Tor implementation trusts all local users, and - * the controller can authenticate itself by calling authenticate(new byte[0]). -- * -+ * <p> - * If the 'CookieAuthentication' option is true, Tor writes a "magic cookie" - * file named "control_auth_cookie" into its data directory. To authenticate, - * the controller must send the contents of this file in <b>auth</b>. -- * -+ * <p> - * If the 'HashedControlPassword' option is set, <b>auth</b> must contain the salted - * hash of a secret password. The salted hash is computed according to the - * S2K algorithm in RFC 2440 (OpenPGP), and prefixed with the s2k specifier. - * This is then encoded in hexadecimal, prefixed by the indicator sequence - * "16:". -- * -+ * <p> - * You can generate the salt of a password by calling -- * 'tor --hash-password <password>' -+ * <tt>'tor --hash-password <password>'</tt> - * or by using the provided PasswordDigest class. -+ * <p> - * To authenticate under this scheme, the controller sends Tor the original - * secret that was used to generate the password. - */ -@@ -505,9 +511,6 @@ - Waiter w = new Waiter(); - if (debugOutput != null) - debugOutput.print(">> "+s); -- if (this.thread != null) { -- this.thread.stopListening(); -- } - synchronized (waiters) { - output.write(s); - output.flush(); -@@ -519,7 +522,7 @@ - * addresses should be replaced with connections to the specified replacement - * addresses. Each element of <b>kvLines</b> is a String of the form - * "old-address new-address". This function returns the new address mapping. -- * -+ * <p> - * The client may decline to provide a body for the original address, and - * instead send a special null address ("0.0.0.0" for IPv4, "::0" for IPv6, or - * "." for hostname), signifying that the server should choose the original -@@ -527,56 +530,52 @@ - * should ensure that it returns an element of address space that is unlikely - * to be in actual use. If there is already an address mapped to the - * destination address, the server may reuse that mapping. -- * -+ * <p> - * If the original address is already mapped to a different address, the old - * mapping is removed. If the original address and the destination address - * are the same, the server removes any mapping in place for the original - * address. -- * -+ * <p> - * Mappings set by the controller last until the Tor process exits: - * they never expire. If the controller wants the mapping to last only - * a certain time, then it must explicitly un-map the address when that - * time has elapsed. - */ - public Map<String,String> mapAddresses(Collection<String> kvLines) throws IOException { -- StringBuffer sb = new StringBuffer("MAPADDRESS"); -- for (Iterator<String> it = kvLines.iterator(); it.hasNext(); ) { -- String kv = it.next(); -+ StringBuilder sb = new StringBuilder("MAPADDRESS"); -+ for (String kv : kvLines) { - int i = kv.indexOf(' '); -- sb.append(" ").append(kv.substring(0,i)).append("=") -- .append(quote(kv.substring(i+1))); -+ sb.append(" ").append(kv.substring(0,i)).append("="); -+ sb.append(quote(kv.substring(i+1))); - } - sb.append("\r\n"); - List<ReplyLine> lst = sendAndWaitForResponse(sb.toString(), null); - Map<String,String> result = new HashMap<String,String>(); -- for (Iterator<ReplyLine> it = lst.iterator(); it.hasNext(); ) { -- String kv = (it.next()).msg; -+ for (ReplyLine line : lst) { -+ String kv = line.msg; - int idx = kv.indexOf('='); -- result.put(kv.substring(0, idx), -- kv.substring(idx+1)); -+ result.put(kv.substring(0, idx), kv.substring(idx+1)); - } - return result; - } - - public Map<String,String> mapAddresses(Map<String,String> addresses) throws IOException { - List<String> kvList = new ArrayList<String>(); -- for (Iterator<Map.Entry<String, String>> it = addresses.entrySet().iterator(); it.hasNext(); ) { -- Map.Entry<String,String> e = it.next(); -+ for (Map.Entry<String,String> e : addresses.entrySet()) { - kvList.add(e.getKey()+" "+e.getValue()); - } - return mapAddresses(kvList); - } - - public String mapAddress(String fromAddr, String toAddr) throws IOException { -- List<String> lst = new ArrayList<String>(); -- lst.add(fromAddr+" "+toAddr+"\n"); -- Map<String,String> m = mapAddresses(lst); -+ String s = fromAddr+" "+toAddr+"\n"; -+ Map<String,String> m = mapAddresses(Arrays.asList(s)); - return m.get(fromAddr); - } - - /** Queries the Tor server for keyed values that are not stored in the torrc - * configuration file. Returns a map of keys to values. -- * -+ * <p> - * Recognized keys include: - * <ul> - * <li>"version" : The version of the server's software, including the name -@@ -605,17 +604,16 @@ - * </ul> - */ - public Map<String,String> getInfo(Collection<String> keys) throws IOException { -- StringBuffer sb = new StringBuffer("GETINFO"); -- for (Iterator<String> it = keys.iterator(); it.hasNext(); ) { -- sb.append(" ").append(it.next()); -+ StringBuilder sb = new StringBuilder("GETINFO"); -+ for (String key : keys) { -+ sb.append(" ").append(key); - } - sb.append("\r\n"); - List<ReplyLine> lst = sendAndWaitForResponse(sb.toString(), null); - Map<String,String> m = new HashMap<String,String>(); -- for (Iterator<ReplyLine> it = lst.iterator(); it.hasNext(); ) { -- ReplyLine line = it.next(); -+ for (ReplyLine line : lst) { - int idx = line.msg.indexOf('='); -- if (idx<0) -+ if (idx == -1) - break; - String k = line.msg.substring(0,idx); - String v; -@@ -629,13 +627,9 @@ - return m; - } - -- -- -- /** Return the value of the information field 'key' */ -+ /** Returns the value of the information field 'key' */ - public String getInfo(String key) throws IOException { -- List<String> lst = new ArrayList<String>(); -- lst.add(key); -- Map<String,String> m = getInfo(lst); -+ Map<String,String> m = getInfo(Arrays.asList(key)); - return m.get(key); - } - -@@ -644,40 +638,39 @@ - * to the specified path, or the <b>circID</b> is nonzero, in which case it is a - * request for the server to extend an existing circuit with that ID according - * to the specified <b>path</b>. -- * -+ * <p> - * If successful, returns the Circuit ID of the (maybe newly created) circuit. - */ - public String extendCircuit(String circID, String path) throws IOException { - List<ReplyLine> lst = sendAndWaitForResponse( - "EXTENDCIRCUIT "+circID+" "+path+"\r\n", null); -- return (lst.get(0)).msg; -+ return lst.get(0).msg; - } - - /** Informs the Tor server that the stream specified by <b>streamID</b> should be - * associated with the circuit specified by <b>circID</b>. -- * -+ * <p> - * Each stream may be associated with - * at most one circuit, and multiple streams may share the same circuit. - * Streams can only be attached to completed circuits (that is, circuits that - * have sent a circuit status "BUILT" event or are listed as built in a - * getInfo circuit-status request). -- * -+ * <p> - * If <b>circID</b> is 0, responsibility for attaching the given stream is - * returned to Tor. -- * -+ * <p> - * By default, Tor automatically attaches streams to - * circuits itself, unless the configuration variable - * "__LeaveStreamsUnattached" is set to "1". Attempting to attach streams - * via TC when "__LeaveStreamsUnattached" is false may cause a race between - * Tor and the controller, as both attempt to attach streams to circuits. - */ -- public void attachStream(String streamID, String circID) -- throws IOException { -+ public void attachStream(String streamID, String circID) throws IOException { - sendAndWaitForResponse("ATTACHSTREAM "+streamID+" "+circID+"\r\n", null); - } - - /** Tells Tor about the server descriptor in <b>desc</b>. -- * -+ * <p> - * The descriptor, when parsed, must contain a number of well-specified - * fields, including fields for its nickname and identity. - */ -@@ -685,12 +678,12 @@ - // No need for return value? control-spec.txt says reply is merely "250 OK" on success... - public String postDescriptor(String desc) throws IOException { - List<ReplyLine> lst = sendAndWaitForResponse("+POSTDESCRIPTOR\r\n", desc); -- return (lst.get(0)).msg; -+ return lst.get(0).msg; - } - - /** Tells Tor to change the exit address of the stream identified by <b>streamID</b> - * to <b>address</b>. No remapping is performed on the new provided address. -- * -+ * <p> - * To be sure that the modified address will be used, this event must be sent - * after a new stream event is received, and before attaching this stream to - * a circuit. -@@ -720,8 +713,7 @@ - * - * Tor may hold the stream open for a while to flush any data that is pending. - */ -- public void closeStream(String streamID, byte reason) -- throws IOException { -+ public void closeStream(String streamID, byte reason) throws IOException { - sendAndWaitForResponse("CLOSESTREAM "+streamID+" "+reason+"\r\n",null); - } - -@@ -729,8 +721,15 @@ - * If <b>ifUnused</b> is true, do not close the circuit unless it is unused. - */ - public void closeCircuit(String circID, boolean ifUnused) throws IOException { -- sendAndWaitForResponse("CLOSECIRCUIT "+circID+ -- (ifUnused?" IFUNUSED":"")+"\r\n", null); -+ String arg = ifUnused ? " IFUNUSED" : ""; -+ sendAndWaitForResponse("CLOSECIRCUIT "+circID+arg+"\r\n", null); -+ } + + /** Tells Tor to exit when this control connection is closed. This command + * was added in Tor 0.2.2.28-beta. + */ + public void takeOwnership() throws IOException { + sendAndWaitForResponse("TAKEOWNERSHIP\r\n", null); - } ++ } } -diff -Bbur jtorctl/net/freehaven/tor/control/TorControlError.java jtorctl-briar/net/freehaven/tor/control/TorControlError.java ---- jtorctl/net/freehaven/tor/control/TorControlError.java 2014-04-02 11:26:56.000000000 +0100 -+++ jtorctl-briar/net/freehaven/tor/control/TorControlError.java 2014-04-02 12:28:01.000000000 +0100 -@@ -2,13 +2,17 @@ - // See LICENSE file for copying information - package net.freehaven.tor.control; - -+import java.io.IOException; -+ - /** - * An exception raised when Tor tells us about an error. - */ --public class TorControlError extends RuntimeException { -- static final long serialVersionUID = 2; -+public class TorControlError extends IOException { -+ -+ private static final long serialVersionUID = 3; -+ -+ private final int errorType; - -- int errorType; - public TorControlError(int type, String s) { - super(s); - errorType = type; -diff -Bbur jtorctl/net/freehaven/tor/control/TorControlSyntaxError.java jtorctl-briar/net/freehaven/tor/control/TorControlSyntaxError.java ---- jtorctl/net/freehaven/tor/control/TorControlSyntaxError.java 2014-04-02 11:26:56.000000000 +0100 -+++ jtorctl-briar/net/freehaven/tor/control/TorControlSyntaxError.java 2014-04-02 12:27:52.000000000 +0100 -@@ -2,12 +2,16 @@ - // See LICENSE file for copying information - package net.freehaven.tor.control; - -+import java.io.IOException; -+ - /** - * An exception raised when Tor behaves in an unexpected way. - */ --public class TorControlSyntaxError extends RuntimeException { -- static final long serialVersionUID = 2; -+public class TorControlSyntaxError extends IOException { - -- public TorControlSyntaxError(String s) { super(s); } --} -+ private static final long serialVersionUID = 3; - -+ public TorControlSyntaxError(String s) { -+ super(s); -+ } -+} -- GitLab