diff --git a/jtorctl.patch b/jtorctl.patch index f50af04820966b8b75d2c76994732307dda28c57..cc027d633cae0a8fabf05922bc3bdf346d5b0977 100644 --- a/jtorctl.patch +++ b/jtorctl.patch @@ -1,320 +1,47 @@ -diff -Bbur jtorctl/net/freehaven/tor/control/Bytes.java jtorctl-briar/net/freehaven/tor/control/Bytes.java ---- jtorctl/net/freehaven/tor/control/Bytes.java 2013-04-24 16:46:08.000000000 +0100 -+++ jtorctl-briar/net/freehaven/tor/control/Bytes.java 2013-05-16 19:56:30.000000000 +0100 -@@ -16,46 +16,43 @@ - /** Write the two-byte value in 's' into the byte array 'ba', starting at - * the index 'pos'. */ - public static void setU16(byte[] ba, int pos, short s) { -- ba[pos] = (byte)((s >> 8) & 0xff); -- ba[pos+1] = (byte)((s ) & 0xff); -+ ba[pos] = (byte) ((s >> 8) & 0xff); -+ ba[pos + 1] = (byte) (s & 0xff); - } - - /** Write the four-byte value in 'i' into the byte array 'ba', starting at - * the index 'pos'. */ - public static void setU32(byte[] ba, int pos, int i) { -- ba[pos] = (byte)((i >> 24) & 0xff); -- ba[pos+1] = (byte)((i >> 16) & 0xff); -- ba[pos+2] = (byte)((i >> 8) & 0xff); -- ba[pos+3] = (byte)((i ) & 0xff); -+ ba[pos] = (byte) ((i >> 24) & 0xff); -+ ba[pos + 1] = (byte) ((i >> 16) & 0xff); -+ ba[pos + 2] = (byte) ((i >> 8) & 0xff); -+ ba[pos + 3] = (byte) (i & 0xff); - } - - /** Return the four-byte value starting at index 'pos' within 'ba' */ - public static int getU32(byte[] ba, int pos) { -- return -- ((ba[pos ]&0xff)<<24) | -- ((ba[pos+1]&0xff)<<16) | -- ((ba[pos+2]&0xff)<< 8) | -- ((ba[pos+3]&0xff)); -+ return ((ba[pos] & 0xff) << 24) | -+ ((ba[pos + 1] & 0xff) << 16) | -+ ((ba[pos + 2] & 0xff) << 8) | -+ ((ba[pos + 3] & 0xff)); - } - - public static String getU32S(byte[] ba, int pos) { -- return String.valueOf( (getU32(ba,pos))&0xffffffffL ); -+ return String.valueOf((getU32(ba, pos)) & 0xffffffffL); - } - - /** Return the two-byte value starting at index 'pos' within 'ba' */ - public static int getU16(byte[] ba, int pos) { -- return -- ((ba[pos ]&0xff)<<8) | -- ((ba[pos+1]&0xff)); -+ return ((ba[pos] & 0xff) << 8) | -+ ((ba[pos + 1] & 0xff)); - } - - /** Return the string starting at position 'pos' of ba and extending - * until a zero byte or the end of the string. */ - public static String getNulTerminatedStr(byte[] ba, int pos) { -- int len, maxlen = ba.length-pos; -- for (len=0; len<maxlen; ++len) { -- if (ba[pos+len] == 0) -- break; -+ int len, maxlen = ba.length - pos; -+ for(len = 0; len < maxlen; ++len) { -+ if(ba[pos + len] == 0) break; - } - return new String(ba, pos, len); - } -@@ -64,18 +61,16 @@ - * Read bytes from 'ba' starting at 'pos', dividing them into strings - * along the character in 'split' and writing them into 'lst' - */ -- public static void splitStr(List<String> lst, byte[] ba, int pos, byte split) { -- while (pos < ba.length && ba[pos] != 0) { -+ public static void splitStr(List<String> lst, byte[] ba, int pos, -+ byte split) { -+ while(pos < ba.length && ba[pos] != 0) { - int len; -- for (len=0; pos+len < ba.length; ++len) { -- if (ba[pos+len] == 0 || ba[pos+len] == split) -- break; -+ for(len = 0; pos + len < ba.length; ++len) { -+ if(ba[pos + len] == 0 || ba[pos + len] == split) break; - } -- if (len>0) -- lst.add(new String(ba, pos, len)); -+ if(len > 0) lst.add(new String(ba, pos, len)); - pos += len; -- if (ba[pos] == split) -- ++pos; -+ if(ba[pos] == split) ++pos; - } - } - -@@ -86,11 +81,8 @@ - public static List<String> splitStr(List<String> lst, String str) { - // split string on spaces, include trailing/leading - String[] tokenArray = str.split(" ", -1); -- if (lst == null) { -- lst = Arrays.asList( tokenArray ); -- } else { -- lst.addAll( Arrays.asList( tokenArray ) ); -- } -+ if(lst == null) lst = Arrays.asList(tokenArray); -+ else lst.addAll(Arrays.asList(tokenArray)); - return lst; - } - -@@ -101,10 +93,10 @@ - - public static final String hex(byte[] ba) { - StringBuffer buf = new StringBuffer(); -- for (int i = 0; i < ba.length; ++i) { -- int b = (ba[i]) & 0xff; -+ for(int i = 0; i < ba.length; ++i) { -+ int b = ba[i] & 0xff; - buf.append(NYBBLES[b >> 4]); -- buf.append(NYBBLES[b&0x0f]); -+ buf.append(NYBBLES[b & 0x0f]); - } - return buf.toString(); - } -diff -Bbur jtorctl/net/freehaven/tor/control/ConfigEntry.java jtorctl-briar/net/freehaven/tor/control/ConfigEntry.java ---- jtorctl/net/freehaven/tor/control/ConfigEntry.java 2013-04-24 16:46:08.000000000 +0100 -+++ jtorctl-briar/net/freehaven/tor/control/ConfigEntry.java 2013-05-16 19:56:30.000000000 +0100 -@@ -4,6 +4,11 @@ - - /** A single key-value pair from Tor's configuration. */ - public class ConfigEntry { -+ -+ public final String key; -+ public final String value; -+ public final boolean is_default; -+ - public ConfigEntry(String k, String v) { - key = k; - value = v; -@@ -14,7 +20,4 @@ - value = ""; - is_default = true; - } -- public final String key; -- public final String value; -- public final boolean is_default; - } -diff -Bbur jtorctl/net/freehaven/tor/control/EventHandler.java jtorctl-briar/net/freehaven/tor/control/EventHandler.java ---- jtorctl/net/freehaven/tor/control/EventHandler.java 2013-04-24 16:46:08.000000000 +0100 -+++ jtorctl-briar/net/freehaven/tor/control/EventHandler.java 2013-05-16 19:56:30.000000000 +0100 -@@ -9,9 +9,10 @@ - * @see TorControlConnection#setEvents - */ - public interface EventHandler { -+ - /** -- * Invoked when a circuit's status has changed. -- * Possible values for <b>status</b> are: -+ * Invoked when a circuit's status has changed. Possible values for -+ * <b>status</b> are: - * <ul> - * <li>"LAUNCHED" : circuit ID assigned to new circuit</li> - * <li>"BUILT" : all hops finished, can now accept streams</li> -@@ -19,7 +20,6 @@ - * <li>"FAILED" : circuit closed (was not built)</li> - * <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. - */ -@@ -24,9 +24,10 @@ - * and <b>path</b> is a comma-separated list of alphanumeric ServerIDs. - */ - public void circuitStatus(String status, String circID, String path); -+ - /** -- * Invoked when a stream's status has changed. -- * Possible values for <b>status</b> are: -+ * Invoked when a stream's status has changed. Possible values for -+ * <b>status</b> are: - * <ul> - * <li>"NEW" : New request to connect</li> - * <li>"NEWRESOLVE" : New request to resolve an address</li> -@@ -37,7 +38,6 @@ - * <li>"CLOSED" : Stream closed</li> - * <li>"DETACHED" : Detached from circuit; still retriable.</li> - * </ul> -- * - * <b>streamID</b> is the alphanumeric identifier of the affected stream, - * and its <b>target</b> is specified as address:port. - */ -@@ -42,18 +42,21 @@ - * and its <b>target</b> is specified as address:port. - */ - public void streamStatus(String status, String streamID, String target); -+ - /** -- * Invoked when the status of a connection to an OR has changed. -- * Possible values for <b>status</b> are ["LAUNCHED" | "CONNECTED" | "FAILED" | "CLOSED"]. -- * <b>orName</b> is the alphanumeric identifier of the OR affected. -+ * Invoked when the status of a connection to an OR has changed. Possible -+ * values for <b>status</b> are ["LAUNCHED" | "CONNECTED" | "FAILED" | -+ * "CLOSED"]. <b>orName</b> is the alphanumeric identifier of the OR -+ * affected. - */ - public void orConnStatus(String status, String orName); -+ - /** -- * Invoked once per second. <b>read</b> and <b>written</b> are -- * the number of bytes read and written, respectively, in -- * the last second. -+ * Invoked once per second. <b>read</b> and <b>written</b> are the number -+ * of bytes read and written, respectively, in the last second. - */ - public void bandwidthUsed(long read, long written); -+ - /** - * Invoked whenever Tor learns about new ORs. The <b>orList</b> object - * contains the alphanumeric ServerIDs associated with the new ORs. -@@ -59,17 +62,18 @@ - * contains the alphanumeric ServerIDs associated with the new ORs. - */ - public void newDescriptors(java.util.List<String> orList); -+ - /** -- * Invoked when Tor logs a message. -- * <b>severity</b> is one of ["DEBUG" | "INFO" | "NOTICE" | "WARN" | "ERR"], -- * and <b>msg</b> is the message string. -+ * Invoked when Tor logs a message. <b>severity</b> is one of ["DEBUG" | -+ * "INFO" | "NOTICE" | "WARN" | "ERR"], and <b>msg</b> is the message -+ * string. - */ - public void message(String severity, String msg); -+ - /** -- * Invoked when an unspecified message is received. -- * <type> is the message type, and <msg> is the message string. -+ * Invoked when an unspecified message is received. <type> is the message -+ * type, and <msg> is the message string. - */ - public void unrecognized(String type, String msg); -- - } - 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 2013-04-24 16:46:08.000000000 +0100 -+++ jtorctl-briar/net/freehaven/tor/control/examples/DebuggingEventHandler.java 2013-05-16 19:56:30.000000000 +0100 -@@ -3,42 +3,48 @@ +--- 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; -+ public DebuggingEventHandler(PrintWriter out) { -+ this.out = out; - } ++ private final PrintWriter out; - public void circuitStatus(String status, String circID, String path) { -- out.println("Circuit "+circID+" is now "+status+" (path="+path+")"); -+ out.println("Circuit " + circID + " is now " + status + -+ " (path=" + path + ")"); - } -+ - public void streamStatus(String status, String streamID, String target) { -- out.println("Stream "+streamID+" is now "+status+" (target="+target+")"); -+ out.println("Stream " + streamID + " is now " + status + -+ " (target=" + target + ")"); - } -+ - public void orConnStatus(String status, String orName) { -- out.println("OR connection to "+orName+" is now "+status); -+ out.println("OR connection to " + orName + " is now " + status); - } -+ - public void bandwidthUsed(long read, long written) { -- out.println("Bandwidth usage: "+read+" bytes read; "+ -- written+" bytes written."); -+ out.println("Bandwidth usage: " + read + " bytes read; " + -+ written +" bytes written."); + 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) { ++ 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); ++ for (String or : orList) ++ out.println(" "+or); } + public void message(String type, String msg) { -- out.println("["+type+"] "+msg.trim()); -+ out.println("[" + type + "] " + msg.trim()); + out.println("["+type+"] "+msg.trim()); } - - public void unrecognized(String type, String msg) { -- out.println("unrecognized event ["+type+"] "+msg.trim()); -+ out.println("unrecognized event [" + 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 2013-04-24 16:46:08.000000000 +0100 -+++ jtorctl-briar/net/freehaven/tor/control/examples/Main.java 2013-05-16 19:56:30.000000000 +0100 -@@ -2,59 +2,60 @@ +--- 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.PrintWriter; +import java.io.EOFException; import java.io.IOException; +import java.io.PrintWriter; @@ -326,52 +53,22 @@ diff -Bbur jtorctl/net/freehaven/tor/control/examples/Main.java jtorctl-briar/ne import java.util.Map; -import java.util.Iterator; + -+import net.freehaven.tor.control.ConfigEntry; -+import net.freehaven.tor.control.PasswordDigest; -+import net.freehaven.tor.control.TorControlCommands; -+import net.freehaven.tor.control.TorControlConnection; -+import net.freehaven.tor.control.TorControlError; ++import net.freehaven.tor.control.*; public class Main implements TorControlCommands { - public static void main(String args[]) { -- if (args.length < 1) { -+ if(args.length < 1) { - System.err.println("No command given."); - return; - } - try { -- if (args[0].equals("set-config")) { -+ if(args[0].equals("set-config")) { - setConfig(args); -- } else if (args[0].equals("get-config")) { -+ } else if(args[0].equals("get-config")) { - getConfig(args); -- } else if (args[0].equals("get-info")) { -+ } else if(args[0].equals("get-info")) { - getInfo(args); -- } else if (args[0].equals("listen")) { -+ } else if(args[0].equals("listen")) { - listenForEvents(args); -- } else if (args[0].equals("signal")) { -+ } else if(args[0].equals("signal")) { - signal(args); -- } else if (args[0].equals("auth")) { -+ } else if(args[0].equals("auth")) { - authDemo(args); +@@ -34,27 +37,22 @@ } else { System.err.println("Unrecognized command: "+args[0]); } - } catch (java.io.EOFException ex) { -+ } catch(EOFException ex) { ++ } catch (EOFException ex) { System.out.println("Control socket closed by Tor."); -- } catch (IOException ex) { -- System.err.println("IO exception when talking to Tor process: "+ -+ } 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: " + ++ } 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) { @@ -389,64 +86,39 @@ diff -Bbur jtorctl/net/freehaven/tor/control/examples/Main.java jtorctl-briar/ne - // 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); ++ 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; -@@ -71,57 +72,52 @@ - ArrayList<String> lst = new ArrayList<String>(); - int i = 1; - boolean save = false; -- if (args[i].equals("-save")) { -+ if(args[i].equals("-save")) { - save = true; - ++i; - } -- for (; i < args.length; i +=2) { -- lst.add(args[i]+" "+args[i+1]); -+ for(; i < args.length; i +=2) { -+ lst.add(args[i] + " " + args[i + 1]); - } - conn.setConf(lst); -- if (save) { -- conn.saveConf(); -- } -+ if(save) conn.saveConf(); - } - +@@ -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(); -- System.out.println("KEY: "+e.key); -- System.out.println("VAL: "+e.value); -+ 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); ++ 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(); -- System.out.println("KEY: "+e.getKey()); -- System.out.println("VAL: "+e.getValue()); -+ 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()); ++ 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); @@ -454,23 +126,11 @@ diff -Bbur jtorctl/net/freehaven/tor/control/examples/Main.java jtorctl-briar/ne - for (int i = 1; i < args.length; ++i) { - lst.add(args[i]); - } -+ List<String> events = Arrays.asList(args).subList(1, args.length); ++ List<String> lst = Arrays.asList(args).subList(1, args.length); conn.setEventHandler( new DebuggingEventHandler(new PrintWriter(System.out, true))); -- conn.setEvents(lst); -+ conn.setEvents(events); - } - - public static void signal(String[] args) throws IOException { - // Usage signal [reload|shutdown|dump|debug|halt] - TorControlConnection conn = getConnection(args, false); - // distinguish shutdown signal from other signals -- if ("SHUTDOWN".equalsIgnoreCase(args[1]) -+ if("SHUTDOWN".equalsIgnoreCase(args[1]) - || "HALT".equalsIgnoreCase(args[1])) { - conn.shutdownTor(args[1].toUpperCase()); - } else { -@@ -130,17 +126,13 @@ + conn.setEvents(lst); +@@ -130,17 +125,13 @@ } public static void authDemo(String[] args) throws IOException { @@ -478,8 +138,8 @@ diff -Bbur jtorctl/net/freehaven/tor/control/examples/Main.java jtorctl-briar/ne 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 Socket("127.0.0.1", 9100); -+ TorControlConnection conn = new TorControlConnection(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]); - @@ -487,14 +147,14 @@ diff -Bbur jtorctl/net/freehaven/tor/control/examples/Main.java jtorctl-briar/ne - - conn = TorControlConnection.getConnection( - new java.net.Socket("127.0.0.1", 9100)); -+ conn = new TorControlConnection(new 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/PasswordDigest.java jtorctl-briar/net/freehaven/tor/control/PasswordDigest.java ---- jtorctl/net/freehaven/tor/control/PasswordDigest.java 2013-04-24 16:46:08.000000000 +0100 -+++ jtorctl-briar/net/freehaven/tor/control/PasswordDigest.java 2013-05-16 19:56:30.000000000 +0100 -@@ -2,19 +2,20 @@ +--- 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; @@ -502,74 +162,36 @@ diff -Bbur jtorctl/net/freehaven/tor/control/PasswordDigest.java jtorctl-briar/n import java.security.SecureRandom; import java.security.MessageDigest; - /** -- * A hashed digest of a secret password (used to set control connection -+ * A hashed digest of a secret password(used to set control connection - * security.) - * - * For the actual hashing algorithm, see RFC2440's secret-to-key conversion. +@@ -13,8 +14,8 @@ */ public class PasswordDigest { - byte[] secret; - String hashedKey; -+ private final byte[] secret; -+ private final 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() { -@@ -35,17 +36,16 @@ - */ - public PasswordDigest(byte[] secret, byte[] specifier) { - this.secret = secret.clone(); -- if (specifier == null) { -+ if(specifier == null) { - specifier = new byte[9]; - SecureRandom rng = new SecureRandom(); +@@ -41,7 +42,7 @@ rng.nextBytes(specifier); specifier[8] = 96; } - hashedKey = "16:"+encodeBytes(secretToKey(secret, specifier)); -+ hashedKey = "16:" + Bytes.hex(secretToKey(secret, specifier)); ++ hashedKey = "16:"+Bytes.hex(secretToKey(secret, specifier)); } -- /** Return the secret used to generate this password hash. -- */ -+ /** Return the secret used to generate this password hash. */ - public byte[] getSecret() { - return secret.clone(); - } -@@ -63,17 +63,17 @@ + /** 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) { ++ } catch (NoSuchAlgorithmException ex) { throw new RuntimeException("Can't run without sha-1."); } -- int c = (specifier[8])&0xff; -- int count = (16 + (c&15)) << ((c>>4) + EXPBIAS); -+ int c = specifier[8] & 0xff; -+ int count = (16 + (c & 15)) << ((c >> 4) + EXPBIAS); - -- byte[] tmp = new byte[8+secret.length]; -+ byte[] tmp = new byte[8 + secret.length]; - System.arraycopy(specifier, 0, tmp, 0, 8); - System.arraycopy(secret, 0, tmp, 8, secret.length); -- while (count > 0) { -- if (count >= tmp.length) { -+ while(count > 0) { -+ if(count >= tmp.length) { - d.update(tmp); - count -= tmp.length; - } else { -@@ -81,17 +81,9 @@ - count = 0; - } - } -- byte[] key = new byte[20+9]; -+ byte[] key = new byte[20 + 9]; - System.arraycopy(d.digest(), 0, key, 9, 20); + int c = (specifier[8])&0xff; +@@ -86,12 +87,5 @@ System.arraycopy(specifier, 0, key, 0, 9); return key; } @@ -581,26 +203,11 @@ diff -Bbur jtorctl/net/freehaven/tor/control/PasswordDigest.java jtorctl-briar/n - } - } -- -diff -Bbur jtorctl/net/freehaven/tor/control/TorControlCommands.java jtorctl-briar/net/freehaven/tor/control/TorControlCommands.java ---- jtorctl/net/freehaven/tor/control/TorControlCommands.java 2013-04-24 16:46:08.000000000 +0100 -+++ jtorctl-briar/net/freehaven/tor/control/TorControlCommands.java 2013-05-16 19:56:30.000000000 +0100 -@@ -119,7 +119,10 @@ - public static final byte OR_CONN_STATUS_CLOSED = 0x03; - - public static final String[] OR_CONN_STATUS_NAMES = { -- "LAUNCHED","CONNECTED","FAILED","CLOSED" -+ "LAUNCHED", -+ "CONNECTED", -+ "FAILED", -+ "CLOSED" - }; - public static final byte SIGNAL_HUP = 0x01; diff -Bbur jtorctl/net/freehaven/tor/control/TorControlConnection.java jtorctl-briar/net/freehaven/tor/control/TorControlConnection.java ---- jtorctl/net/freehaven/tor/control/TorControlConnection.java 2013-04-24 16:46:08.000000000 +0100 -+++ jtorctl-briar/net/freehaven/tor/control/TorControlConnection.java 2013-05-16 19:56:30.000000000 +0100 -@@ -2,120 +2,107 @@ +--- jtorctl/net/freehaven/tor/control/TorControlConnection.java 2014-04-02 11:26:56.000000000 +0100 ++++ jtorctl-briar/net/freehaven/tor/control/TorControlConnection.java 2014-04-02 12:29:34.000000000 +0100 +@@ -2,96 +2,93 @@ // See LICENSE file for copying information package net.freehaven.tor.control; @@ -633,20 +240,20 @@ diff -Bbur jtorctl/net/freehaven/tor/control/TorControlConnection.java jtorctl-b +public class TorControlConnection implements TorControlCommands { - protected EventHandler handler; -+ private final LinkedList<Waiter> waiters; -+ private final BufferedReader input; -+ private final Writer output; ++ private final LinkedList<Waiter> waiters; ++ private final BufferedReader input; ++ private final Writer output; - protected LinkedList<Waiter> waiters; -+ private ControlParseThread thread; // Locking: this ++ private ControlParseThread thread; // Locking: this - protected ControlParseThread thread; -+ private volatile EventHandler handler; -+ private volatile PrintWriter debugOutput; -+ private volatile IOException parseThreadException; ++ private volatile EventHandler handler; ++ private volatile PrintWriter debugOutput; ++ private volatile IOException parseThreadException; - protected java.io.BufferedReader input; -+ private static class Waiter { ++ private static class Waiter { - protected java.io.Writer output; - @@ -656,21 +263,20 @@ diff -Bbur jtorctl/net/freehaven/tor/control/TorControlConnection.java jtorctl-b List<ReplyLine> response; - public synchronized List<ReplyLine> getResponse() { - try { -- while (response == null) { -- wait(); -- } ++ ++ synchronized List<ReplyLine> getResponse() throws InterruptedException { + while (response == null) { + wait(); + } - } catch (InterruptedException ex) { - throw new CancellationException( - "Please don't interrupt library calls."); - } -+ -+ synchronized List<ReplyLine> getResponse() throws InterruptedException { -+ while(response == null) wait(); return response; } - public synchronized void setResponse(List<ReplyLine> response) { + -+ synchronized void setResponse(List<ReplyLine> response) { ++ synchronized void setResponse(List<ReplyLine> response) { this.response = response; notifyAll(); } @@ -680,18 +286,18 @@ diff -Bbur jtorctl/net/freehaven/tor/control/TorControlConnection.java jtorctl-b - public String status; - public String msg; - public String rest; -+ private static class ReplyLine { ++ private static class ReplyLine { + -+ final String status; -+ final String msg; -+ final String rest; ++ 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; ++ this.status = status; ++ this.msg = msg; ++ this.rest = rest; } - - public static TorControlConnection getConnection(java.net.Socket sock) @@ -706,8 +312,8 @@ diff -Bbur jtorctl/net/freehaven/tor/control/TorControlConnection.java jtorctl-b - public TorControlConnection(java.net.Socket connection) - throws IOException { - this(connection.getInputStream(), connection.getOutputStream()); -+ public TorControlConnection(Socket s) throws IOException { -+ this(s.getInputStream(), s.getOutputStream()); ++ public TorControlConnection(Socket s) throws IOException { ++ this(s.getInputStream(), s.getOutputStream()); } /** Create a new TorControlConnection to communicate with Tor over @@ -716,142 +322,78 @@ diff -Bbur jtorctl/net/freehaven/tor/control/TorControlConnection.java jtorctl-b - 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(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; -- else ++ 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>(); -+ public TorControlConnection(Reader i, Writer o) { -+ if(i instanceof BufferedReader) input = (BufferedReader) i; -+ else input = new BufferedReader(i); -+ output = o; -+ waiters = new LinkedList<Waiter>(); ++ input = new BufferedReader(i); ++ output = o; ++ waiters = new LinkedList<Waiter>(); } - protected final void writeEscaped(String s) throws IOException { -+ private void writeEscaped(String s) throws IOException { ++ private final void writeEscaped(String s) throws IOException { StringTokenizer st = new StringTokenizer(s, "\n"); -- while (st.hasMoreTokens()) { -+ while(st.hasMoreTokens()) { + while (st.hasMoreTokens()) { String line = st.nextToken(); -- if (line.startsWith(".")) -- line = "."+line; -- if (line.endsWith("\r")) -- line += "\n"; -- else -- line += "\r\n"; -- if (debugOutput != null) -- debugOutput.print(">> "+line); -+ if(line.startsWith(".")) line = "." + line; -+ if(line.endsWith("\r")) line += "\n"; -+ else line += "\r\n"; -+ if(debugOutput != null) debugOutput.print(">> " + line); - output.write(line); - } - output.write(".\r\n"); -- if (debugOutput != null) -- debugOutput.print(">> .\n"); -+ if(debugOutput != null) debugOutput.print(">> .\n"); +@@ -110,12 +107,11 @@ + debugOutput.print(">> .\n"); } - protected static final String quote(String s) { -+ private static final String quote(String s) { - StringBuffer sb = new StringBuffer("\""); -- for (int i = 0; i < s.length(); ++i) { -+ for(int i = 0; i < s.length(); ++i) { +- 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) { ++ switch (c) { case '\r': case '\n': case '\\': -@@ -128,15 +115,15 @@ +@@ -128,7 +124,7 @@ return sb.toString(); } - protected final ArrayList<ReplyLine> readReply() throws IOException { -+ private ArrayList<ReplyLine> readReply() throws IOException { ++ private ArrayList<ReplyLine> readReply() throws IOException { ArrayList<ReplyLine> reply = new ArrayList<ReplyLine>(); char c; do { - String line = input.readLine(); -- if (line == null) { -+ if(line == null) { - // if line is null, the end of the stream has been reached, i.e. - // the connection to Tor has been closed! -- if (reply.isEmpty()) { -+ if(reply.isEmpty()) { - // nothing received so far, can exit cleanly - return reply; - } -@@ -144,91 +131,86 @@ - throw new TorControlSyntaxError("Connection to Tor " + - " broke down while receiving reply!"); - } -- if (debugOutput != null) -- debugOutput.println("<< "+line); -- if (line.length() < 4) -- throw new TorControlSyntaxError("Line (\""+line+"\") too short"); -- String status = line.substring(0,3); -+ if(debugOutput != null) debugOutput.println("<< " + line); -+ if(line.length() < 4) { -+ throw new TorControlSyntaxError("Line (\"" + line + -+ "\") too short"); -+ } -+ String status = line.substring(0, 3); - c = line.charAt(3); +@@ -153,7 +149,7 @@ String msg = line.substring(4); String rest = null; -- if (c == '+') { -+ if(c == '+') { - StringBuffer data = new StringBuffer(); -- while (true) { -+ while(true) { + if (c == '+') { +- StringBuffer data = new StringBuffer(); ++ StringBuilder data = new StringBuilder(); + while (true) { line = input.readLine(); -- if (debugOutput != null) -- debugOutput.print("<< "+line); -- if (line.equals(".")) -- break; -- else if (line.startsWith(".")) -- line = line.substring(1); -+ if(debugOutput != null) debugOutput.print("<< " + line); -+ if(line.equals(".")) break; -+ if(line.startsWith(".")) line = line.substring(1); - data.append(line).append('\n'); - } - rest = data.toString(); - } - reply.add(new ReplyLine(status, msg, rest)); -- } while (c != ' '); -- -+ } while(c != ' '); + if (debugOutput != null) +@@ -172,8 +168,9 @@ return reply; } - 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; ++ private synchronized List<ReplyLine> sendAndWaitForResponse(String s, ++ String rest) throws IOException { ++ if(parseThreadException != null) throw parseThreadException; checkThread(); Waiter w = new Waiter(); -- if (debugOutput != null) -- debugOutput.print(">> "+s); -- synchronized (waiters) { -+ if(debugOutput != null) debugOutput.print(">> " + s); -+ synchronized(waiters) { - output.write(s); -- if (rest != null) -- writeEscaped(rest); -+ if(rest != null) writeEscaped(rest); + if (debugOutput != null) +@@ -185,38 +182,38 @@ output.flush(); waiters.addLast(w); } @@ -860,15 +402,15 @@ diff -Bbur jtorctl/net/freehaven/tor/control/TorControlConnection.java jtorctl-b - 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); -+ } -+ for(ReplyLine line : lst) { -+ if(!line.status.startsWith("2")) -+ throw new TorControlError("Error reply: " + line.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; } @@ -876,59 +418,37 @@ diff -Bbur jtorctl/net/freehaven/tor/control/TorControlConnection.java jtorctl-b /** Helper: decode a CMD_EVENT command and dispatch it to our * EventHandler (if any). */ - protected void handleEvent(ArrayList<ReplyLine> events) { -- if (handler == null) -- return; -- ++ private void handleEvent(ArrayList<ReplyLine> events) { + if (handler == null) + return; + - for (Iterator<ReplyLine> i = events.iterator(); i.hasNext(); ) { - ReplyLine line = i.next(); -+ private void handleEvent(ArrayList<ReplyLine> events) { -+ if(handler == null) return; -+ for(ReplyLine line : events) { ++ for (ReplyLine line : events) { int idx = line.msg.indexOf(' '); String tp = line.msg.substring(0, idx).toUpperCase(); String rest = line.msg.substring(idx+1); -- if (tp.equals("CIRC")) { -+ if(tp.equals("CIRC")) { + 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)); -- } else if (tp.equals("STREAM")) { -+ String path; -+ if(lst.get(1).equals("LAUNCHED") || lst.size() < 2) path = ""; -+ else path = lst.get(2); -+ handler.circuitStatus(lst.get(1), lst.get(0), path); -+ } else if(tp.equals("STREAM")) { ++ String path; ++ if (lst.get(1).equals("LAUNCHED") || lst.size() < 3) path = ""; ++ else path = lst.get(2); ++ handler.circuitStatus(lst.get(1), lst.get(0), path); + } 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)); ++ handler.streamStatus(lst.get(1), lst.get(0), lst.get(3)); // XXXX circID. -- } else if (tp.equals("ORCONN")) { -+ } else if(tp.equals("ORCONN")) { + } else if (tp.equals("ORCONN")) { List<String> lst = Bytes.splitStr(null, rest); - handler.orConnStatus(lst.get(1), lst.get(0)); -- } else if (tp.equals("BW")) { -+ } else if(tp.equals("BW")) { - List<String> lst = Bytes.splitStr(null, rest); -- handler.bandwidthUsed(Integer.parseInt(lst.get(0)), -- Integer.parseInt(lst.get(1))); -- } else if (tp.equals("NEWDESC")) { -+ int read = Integer.parseInt(lst.get(0)); -+ int written = Integer.parseInt(lst.get(1)); -+ handler.bandwidthUsed(read, written); -+ } else if(tp.equals("NEWDESC")) { - List<String> lst = Bytes.splitStr(null, rest); - handler.newDescriptors(lst); -- } else if (tp.equals("DEBUG") || -+ } else if(tp.equals("DEBUG") || - tp.equals("INFO") || - tp.equals("NOTICE") || - tp.equals("WARN") || -@@ -240,23 +222,22 @@ +@@ -240,23 +237,22 @@ } } @@ -937,11 +457,11 @@ diff -Bbur jtorctl/net/freehaven/tor/control/TorControlConnection.java jtorctl-b * 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 "\<\<" ++ * Outgoing messages are preceded by "\>\>" and incoming messages are ++ * preceded by "\<\<" */ - public void setDebugging(java.io.PrintWriter w) { -+ public void setDebugging(PrintWriter w) { ++ public void setDebugging(PrintWriter w) { debugOutput = w; } @@ -949,35 +469,34 @@ diff -Bbur jtorctl/net/freehaven/tor/control/TorControlConnection.java jtorctl-b * 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 "\<\<" ++ * 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); ++ public void setDebugging(PrintStream s) { ++ debugOutput = new PrintWriter(s, true); } /** Set the EventHandler object that will be notified of any -@@ -271,52 +252,43 @@ +@@ -271,50 +267,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) { ++ public synchronized Thread launchThread(boolean daemon) { ControlParseThread th = new ControlParseThread(); -- if (daemon) -- th.setDaemon(true); -+ if(daemon) th.setDaemon(true); + if (daemon) + th.setDaemon(true); th.start(); - this.thread = th; -+ thread = th; ++ thread = th; return th; } - protected class ControlParseThread extends Thread { - boolean stopped = false; -+ private class ControlParseThread extends Thread { ++ private class ControlParseThread extends Thread { + @Override public void run() { @@ -987,54 +506,51 @@ diff -Bbur jtorctl/net/freehaven/tor/control/TorControlConnection.java jtorctl-b - if (stopped) // we expected this exception - return; - throw new RuntimeException(ex); -- } catch (IOException ex) { + } catch (IOException ex) { - throw new RuntimeException(ex); -- } -+ } catch(IOException ex) { -+ parseThreadException = ex; ++ parseThreadException = ex; + } } - public void stopListening() { - this.stopped = true; - } +- } } - protected final void checkThread() { -- if (thread == null) -- launchThread(true); -+ private synchronized void checkThread() { -+ if(thread == null) launchThread(true); ++ private synchronized void checkThread() { + if (thread == null) + launchThread(true); } /** helper: implement the main background loop. */ - protected void react() throws IOException { -- while (true) { -+ private void react() throws IOException { -+ while(true) { ++ private void react() throws IOException { + while (true) { ArrayList<ReplyLine> lst = readReply(); -- if (lst.isEmpty()) { -+ if(lst.isEmpty()) { + 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")) { ++ if ((lst.get(0)).status.startsWith("6")) { handleEvent(lst); - else { -+ } else { ++ } else { Waiter w; -- synchronized (waiters) { -+ synchronized(waiters) { + synchronized (waiters) { w = waiters.removeFirst(); - } - w.setResponse(lst); -@@ -327,17 +299,14 @@ - /** Change the value of the configuration option 'key' to 'val'. - */ +@@ -324,20 +313,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)); ++ setConf(Arrays.asList(key+" "+value)); } /** Change the values of the configuration options stored in kvMap. */ @@ -1043,107 +559,87 @@ diff -Bbur jtorctl/net/freehaven/tor/control/TorControlConnection.java jtorctl-b - 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"); ++ for (Map.Entry<String,String> e : kvMap.entrySet()) { ++ lst.add(e.getKey()+" "+e.getValue()+"\n"); } setConf(lst); } -@@ -345,34 +314,35 @@ +@@ -345,34 +330,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> ++ * <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. + * all-or-nothing: if there is an error in any of the configuration settings, + * Tor sets none of them. - * -+ * all-or-nothing: if there is an error in any of the configuration -+ * settings, Tor sets none of them. -+ * <p> ++ * <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. + * 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. - * -+ * 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> ++ * <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. -+ * default value), include a String in <b>kvList</b> containing the key and -+ * no value. + * 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; -+ if(kvList.size() == 0) return; - StringBuffer b = new StringBuffer("SETCONF"); + if (kvList.size() == 0) + return; +- StringBuffer b = new StringBuffer("SETCONF"); - for (Iterator<String> it = kvList.iterator(); it.hasNext(); ) { - String kv = it.next(); -- int i = kv.indexOf(' '); -- if (i == -1) -+ for(String kv : kvList) { -+ int idx = kv.indexOf(' '); -+ if(idx == -1) { ++ 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))); -+ } else { -+ b.append(" ").append(kv.substring(0, idx)); -+ b.append("=").append(quote(kv.substring(idx + 1))); -+ } ++ b.append(" ").append(kv.substring(0,i)).append("="); ++ b.append(quote(kv.substring(i+1))); } b.append("\r\n"); sendAndWaitForResponse(b.toString(), null); -@@ -382,11 +352,9 @@ - * default values. - **/ +@@ -384,9 +368,8 @@ public void resetConf(Collection<String> keys) throws IOException { -- if (keys.size() == 0) -- return; -+ if(keys.size() == 0) return; - StringBuffer b = new StringBuffer("RESETCONF"); + if (keys.size() == 0) + return; +- StringBuffer b = new StringBuffer("RESETCONF"); - for (Iterator<String> it = keys.iterator(); it.hasNext(); ) { - String key = it.next(); -+ for(String key : keys) { ++ StringBuilder b = new StringBuilder("RESETCONF"); ++ for (String key : keys) { b.append(" ").append(key); } b.append("\r\n"); -@@ -400,36 +368,38 @@ - return getConf(lst); - } +@@ -402,10 +385,10 @@ -- /** Requests the values of the configuration variables listed in <b>keys</b>. -- * Results are returned as a list of ConfigEntry objects. + /** Requests the values of the configuration variables listed in <b>keys</b>. + * Results are returned as a list of ConfigEntry objects. - * -+ /** Requests the values of the configuration variables listed in -+ * <b>keys</b>. Results are returned as a list of ConfigEntry objects. -+ * <p> ++ * <p> * If an option appears multiple times in the configuration, all of its * key-value pairs are returned in order. - * -+ * <p> ++ * <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" - * virtual keyword to get all HiddenServiceDir, HiddenServicePort, +@@ -413,23 +396,24 @@ * HiddenServiceNodes, and HiddenServiceExcludeNodes option settings. */ -- public List<ConfigEntry> getConf(Collection<String> keys) throws IOException { -+ public List<ConfigEntry> getConf(Collection<String> keys) -+ throws IOException { - StringBuffer sb = new StringBuffer("GETCONF"); + 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(); -+ for(String key : keys) { ++ StringBuilder sb = new StringBuilder("GETCONF"); ++ for (String key : keys) { sb.append(" ").append(key); } sb.append("\r\n"); @@ -1151,41 +647,40 @@ diff -Bbur jtorctl/net/freehaven/tor/control/TorControlConnection.java jtorctl-b 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; ++ 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 { ++ 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; } -@@ -437,37 +407,41 @@ +@@ -437,37 +421,38 @@ * Each element of <b>events</b> is one of the following Strings: * ["CIRC" | "STREAM" | "ORCONN" | "BW" | "DEBUG" | * "INFO" | "NOTICE" | "WARN" | "ERR" | "NEWDESC" | "ADDRMAP"] . - * -+ * <p> ++ * <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. -+ * setEvents with an empty <b>events</b> argument turns off all event -+ * reporting. + * 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"); +- StringBuffer sb = new StringBuffer("SETEVENTS"); - for (Iterator<String> it = events.iterator(); it.hasNext(); ) { - sb.append(" ").append(it.next()); -+ for(String event : events) { -+ sb.append(" ").append(event); ++ StringBuilder sb = new StringBuilder("SETEVENTS"); ++ for (String event : events) { ++ sb.append(" ").append(event); } sb.append("\r\n"); sendAndWaitForResponse(sb.toString(), null); @@ -1193,494 +688,285 @@ diff -Bbur jtorctl/net/freehaven/tor/control/TorControlConnection.java jtorctl-b /** Authenticates the controller to the Tor server. - * -+ * <p> ++ * <p> * By default, the current Tor implementation trusts all local users, and -- * the controller can authenticate itself by calling authenticate(new byte[0]). + * the controller can authenticate itself by calling authenticate(new byte[0]). - * -- * 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 '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>. - * -- * 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> + * 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:". - * -+ * 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> ++ * <p> * You can generate the salt of a password by calling - * 'tor --hash-password <password>' -+ * <tt>'tor --hash-password <password>'</tt> ++ * <tt>'tor --hash-password <password>'</tt> * or by using the provided PasswordDigest class. -+ * <p> ++ * <p> * To authenticate under this scheme, the controller sends Tor the original * secret that was used to generate the password. */ -@@ -476,7 +450,8 @@ - sendAndWaitForResponse(cmd, null); - } - -- /** Instructs the server to write out its configuration options into its torrc. -+ /** Instructs the server to write out its configuration options into its -+ * torrc. - */ - public void saveConf() throws IOException { - sendAndWaitForResponse("SAVECONF\r\n", null); -@@ -503,234 +478,239 @@ - public void shutdownTor(String signal) throws IOException { - String s = "SIGNAL " + signal + "\r\n"; +@@ -505,9 +490,6 @@ Waiter w = new Waiter(); -- if (debugOutput != null) -- debugOutput.print(">> "+s); + if (debugOutput != null) + debugOutput.print(">> "+s); - if (this.thread != null) { - this.thread.stopListening(); - } -- synchronized (waiters) { -+ if(debugOutput != null) debugOutput.print(">> " + s); -+ synchronized(waiters) { + synchronized (waiters) { output.write(s); output.flush(); - waiters.addLast(w); // Prevent react() from finding the list empty - } - } - -- /** Tells the Tor server that future SOCKS requests for connections to a set of original -- * 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. +@@ -519,7 +501,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. - * -+ /** Tells the Tor server that future SOCKS requests for connections to a -+ * set of original 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> ++ * <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 -- * address itself, and return that address in the reply. The server -- * 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. + * 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 +509,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. - * -- * 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> + * 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. - * -- * 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. -+ * 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 address itself, and return that address in the reply. The -+ * server 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. ++ * <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 { -+ public Map<String, String> mapAddresses(Collection<String> kvLines) -+ throws IOException { - StringBuffer sb = new StringBuffer("MAPADDRESS"); + 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(); -- int i = kv.indexOf(' '); ++ 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))); -+ for(String kv : kvLines) { -+ int idx = kv.indexOf(' '); -+ sb.append(" ").append(kv.substring(0, idx)); -+ sb.append("=").append(quote(kv.substring(idx + 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>(); + Map<String,String> result = new HashMap<String,String>(); - for (Iterator<ReplyLine> it = lst.iterator(); it.hasNext(); ) { - String kv = (it.next()).msg; -+ Map<String, String> result = new HashMap<String, String>(); -+ for(ReplyLine line : lst) { -+ String kv = line.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)); ++ result.put(kv.substring(0, idx), kv.substring(idx+1)); } return result; } -- public Map<String,String> mapAddresses(Map<String,String> addresses) throws IOException { -+ public Map<String, String> mapAddresses(Map<String, String> addresses) -+ throws IOException { + 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(); -- kvList.add(e.getKey()+" "+e.getValue()); -+ for(Map.Entry<String, String> e : addresses.entrySet()) { -+ kvList.add(e.getKey() + " " + e.getValue()); ++ 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 { -+ public String mapAddress(String fromAddr, String toAddr) -+ throws IOException { - List<String> lst = new ArrayList<String>(); + 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); -+ 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. + /** Queries the Tor server for keyed values that are not stored in the torrc + * configuration file. Returns a map of keys to values. - * -+ /** Queries the Tor server for keyed values that are not stored in the -+ * torrc configuration file. Returns a map of keys to values. -+ * <p> ++ * <p> * Recognized keys include: * <ul> * <li>"version" : The version of the server's software, including the name - * of the software. (example: "Tor 0.0.9.4")</li> -- * <li>"desc/id/<OR identity>" or "desc/name/<OR nickname>" : the latest server -- * descriptor for a given OR, NUL-terminated. If no such OR is known, the -- * corresponding value is an empty string.</li> -- * <li>"network-status" : a space-separated list of all known OR identities. -- * This is in the same format as the router-status line in directories; -- * see tor-spec.txt for details.</li> -+ * <li>"desc/id/<OR identity>" or "desc/name/<OR nickname>" : the latest -+ * server descriptor for a given OR, NUL-terminated. If no such OR is -+ * known, the corresponding value is an empty string.</li> -+ * <li>"network-status" : a space-separated list of all known OR -+ * identities. This is in the same format as the router-status line in -+ * directories; see tor-spec.txt for details.</li> - * <li>"addr-mappings/all"</li> - * <li>"addr-mappings/config"</li> - * <li>"addr-mappings/cache"</li> -- * <li>"addr-mappings/control" : a space-separated list of address mappings, each -- * in the form of "from-address=to-address". The 'config' key -- * returns those address mappings set in the configuration; the 'cache' -+ * <li>"addr-mappings/control" : a space-separated list of address -+ * mappings, each in the form of "from-address=to-address". The 'config' -+ * key returns those address mappings set in the configuration; the 'cache' - * key returns the mappings in the client-side DNS cache; the 'control' - * key returns the mappings set via the control interface; the 'all' - * target returns the mappings set through any mechanism.</li> -- * <li>"circuit-status" : A series of lines as for a circuit status event. Each line is of the form: -- * "CircuitID CircStatus Path"</li> -- * <li>"stream-status" : A series of lines as for a stream status event. Each is of the form: -- * "StreamID StreamStatus CircID Target"</li> -- * <li>"orconn-status" : A series of lines as for an OR connection status event. Each is of the -- * form: "ServerID ORStatus"</li> -+ * <li>"circuit-status" : A series of lines as for a circuit status event. -+ * Each line is of the form: "CircuitID CircStatus Path"</li> -+ * <li>"stream-status" : A series of lines as for a stream status event. -+ * Each is of the form: "StreamID StreamStatus CircID Target"</li> -+ * <li>"orconn-status" : A series of lines as for an OR connection status -+ * event. Each is of the form: "ServerID ORStatus"</li> +@@ -605,15 +583,14 @@ * </ul> */ -- public Map<String,String> getInfo(Collection<String> keys) throws IOException { -+ public Map<String, String> getInfo(Collection<String> keys) -+ throws IOException { - StringBuffer sb = new StringBuffer("GETINFO"); + 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()); -+ for(String key : keys) { -+ sb.append(" ").append(key); ++ 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>(); + Map<String,String> m = new HashMap<String,String>(); - for (Iterator<ReplyLine> it = lst.iterator(); it.hasNext(); ) { - ReplyLine line = it.next(); -+ Map<String, String> m = new HashMap<String, String>(); -+ for(ReplyLine line : lst) { ++ for (ReplyLine line : lst) { int idx = line.msg.indexOf('='); -- if (idx<0) -- break; -- String k = line.msg.substring(0,idx); -+ if(idx < 0) break; -+ String k = line.msg.substring(0, idx); - String v; -- if (line.rest != null) { -- v = line.rest; -- } else { -- v = line.msg.substring(idx+1); -- } -+ if(line.rest != null) v = line.rest; -+ else v = line.msg.substring(idx + 1); - m.put(k, v); - } + if (idx<0) + break; +@@ -629,13 +606,9 @@ return m; } - - - /** Return the value of the information field 'key' */ -+ /** Returns 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)); ++ Map<String,String> m = getInfo(Arrays.asList(key)); return m.get(key); } -- /** An extendCircuit request takes one of two forms: either the <b>circID</b> is zero, in -- * which case it is a request for the server to build a new circuit according -- * 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>. +@@ -644,40 +617,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>. - * -- * If successful, returns the Circuit ID of the (maybe newly created) circuit. -+ /** An extendCircuit request takes one of two forms: either the -+ * <b>circID</b> is zero, in which case it is a request for the server to -+ * build a new circuit according 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. ++ * <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); + List<ReplyLine> lst = sendAndWaitForResponse( + "EXTENDCIRCUIT "+circID+" "+path+"\r\n", null); - return (lst.get(0)).msg; -+ String cmd = "EXTENDCIRCUIT " + circID + " " + path + "\r\n"; -+ List<ReplyLine> lst = sendAndWaitForResponse(cmd, 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>. + /** Informs the Tor server that the stream specified by <b>streamID</b> should be + * associated with the circuit specified by <b>circID</b>. - * -- * 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> + * 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). - * -+ /** 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> ++ * <p> * If <b>circID</b> is 0, responsibility for attaching the given stream is * returned to Tor. - * -- * 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. -+ * <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. ++ * <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 { -- sendAndWaitForResponse("ATTACHSTREAM "+streamID+" "+circID+"\r\n", null); -+ String cmd = "ATTACHSTREAM " + streamID + " " + circID + "\r\n"; -+ sendAndWaitForResponse(cmd, null); +- 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> ++ * <p> * The descriptor, when parsed, must contain a number of well-specified * fields, including fields for its nickname and identity. */ - // More documentation here on format of desc? +@@ -685,12 +657,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); + List<ReplyLine> lst = sendAndWaitForResponse("+POSTDESCRIPTOR\r\n", desc); - return (lst.get(0)).msg; -+ String cmd = "+POSTDESCRIPTOR\r\n"; -+ List<ReplyLine> lst = sendAndWaitForResponse(cmd, 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. + /** 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. - * -- * 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. -- */ -- public void redirectStream(String streamID, String address) throws IOException { -- sendAndWaitForResponse("REDIRECTSTREAM "+streamID+" "+address+"\r\n", -- null); -+ /** 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. -+ */ -+ public void redirectStream(String streamID, String address) -+ throws IOException { -+ String cmd = "REDIRECTSTREAM " + streamID + " " + address + "\r\n"; -+ sendAndWaitForResponse(cmd, null); - } - - /** Tells Tor to close the stream identified by <b>streamID</b>. -- * <b>reason</b> should be one of the Tor RELAY_END reasons given in tor-spec.txt, as a decimal: -+ * <b>reason</b> should be one of the Tor RELAY_END reasons given in -+ * tor-spec.txt, as a decimal: - * <ul> - * <li>1 -- REASON_MISC (catch-all for unlisted reasons)</li> - * <li>2 -- REASON_RESOLVEFAILED (couldn't look up hostname)</li> - * <li>3 -- REASON_CONNECTREFUSED (remote host refused connection)</li> -- * <li>4 -- REASON_EXITPOLICY (OR refuses to connect to host or port)</li> -+ * <li>4 -- REASON_EXITPOLICY (OR refuses to connect to host or -+ * port)</li> - * <li>5 -- REASON_DESTROY (Circuit is being destroyed)</li> -- * <li>6 -- REASON_DONE (Anonymized TCP connection was closed)</li> -- * <li>7 -- REASON_TIMEOUT (Connection timed out, or OR timed out while connecting)</li> -+ * <li>6 -- REASON_DONE (Anonymized TCP connection was -+ * closed)</li> -+ * <li>7 -- REASON_TIMEOUT (Connection timed out, or OR timed out -+ * while connecting)</li> - * <li>8 -- (unallocated)</li> - * <li>9 -- REASON_HIBERNATING (OR is temporarily hibernating)</li> - * <li>10 -- REASON_INTERNAL (Internal error at the OR)</li> -- * <li>11 -- REASON_RESOURCELIMIT (OR has no resources to fulfill request)</li> -+ * <li>11 -- REASON_RESOURCELIMIT (OR has no resources to fulfill -+ * request)</li> - * <li>12 -- REASON_CONNRESET (Connection was unexpectedly reset)</li> -- * <li>13 -- REASON_TORPROTOCOL (Sent when closing connection because of Tor protocol violations)</li> -+ * <li>13 -- REASON_TORPROTOCOL (Sent when closing connection because of -+ * Tor protocol violations)</li> - * </ul> -- * -- * Tor may hold the stream open for a while to flush any data that is pending. -+ * Tor may hold the stream open for a while to flush any data that is -+ * pending. ++ * <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 +692,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 { -- sendAndWaitForResponse("CLOSESTREAM "+streamID+" "+reason+"\r\n",null); -+ public void closeStream(String streamID, byte reason) throws IOException { -+ String cmd = "CLOSESTREAM " + streamID + " " + reason + "\r\n"; -+ sendAndWaitForResponse(cmd, null); ++ public void closeStream(String streamID, byte reason) throws IOException { + sendAndWaitForResponse("CLOSESTREAM "+streamID+" "+reason+"\r\n",null); } - /** Tells Tor to close the circuit identified by <b>circID</b>. -- * If <b>ifUnused</b> is true, do not close the circuit unless it is unused. -+ * If <b>ifUnused</b> is true, do not close the circuit unless it is -+ * unused. +@@ -729,8 +700,8 @@ + * If <b>ifUnused</b> is true, do not close the circuit unless it is unused. */ -- public void closeCircuit(String circID, boolean ifUnused) throws IOException { + public void closeCircuit(String circID, boolean ifUnused) throws IOException { - sendAndWaitForResponse("CLOSECIRCUIT "+circID+ - (ifUnused?" IFUNUSED":"")+"\r\n", null); -+ public void closeCircuit(String circID, boolean ifUnused) -+ throws IOException { -+ String cmd; -+ if(ifUnused) cmd = "CLOSECIRCUIT " + circID + " IFUNUSED\r\n"; -+ else cmd = "CLOSECIRCUIT " + circID + "\r\n"; -+ sendAndWaitForResponse(cmd, null); ++ String arg = ifUnused ? " IFUNUSED" : ""; ++ sendAndWaitForResponse("CLOSECIRCUIT "+circID+arg+"\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 2013-04-24 16:46:08.000000000 +0100 -+++ jtorctl-briar/net/freehaven/tor/control/TorControlError.java 2013-05-16 19:56:30.000000000 +0100 -@@ -2,13 +2,15 @@ +--- 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; --/** -- * An exception raised when Tor tells us about an error. -- */ --public class TorControlError extends RuntimeException { -- static final long serialVersionUID = 2; +import java.io.IOException; + -+/** An exception raised when Tor tells us about an error. */ + /** + * 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 = 2; ++ private static final long serialVersionUID = 3; + -+ private final int errorType; ++ private final int errorType; - int errorType; public TorControlError(int type, String s) { super(s); errorType = type; -@@ -19,13 +23,13 @@ - public int getErrorType() { - return errorType; - } -+ - public String getErrorMsg() { - try { -- if (errorType == -1) -- return null; -+ if(errorType == -1) return null; - return TorControlCommands.ERROR_MSGS[errorType]; -- } catch (ArrayIndexOutOfBoundsException ex) { -- return "Unrecongized error #"+errorType; -+ } catch(ArrayIndexOutOfBoundsException ex) { -+ return "Unrecongized error #" + errorType; - } - } - } diff -Bbur jtorctl/net/freehaven/tor/control/TorControlSyntaxError.java jtorctl-briar/net/freehaven/tor/control/TorControlSyntaxError.java ---- jtorctl/net/freehaven/tor/control/TorControlSyntaxError.java 2013-04-24 16:46:08.000000000 +0100 -+++ jtorctl-briar/net/freehaven/tor/control/TorControlSyntaxError.java 2013-05-16 19:56:30.000000000 +0100 -@@ -2,12 +2,15 @@ +--- 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; --/** -- * An exception raised when Tor behaves in an unexpected way. -- */ ++import java.io.IOException; ++ + /** + * An exception raised when Tor behaves in an unexpected way. + */ -public class TorControlSyntaxError extends RuntimeException { - static final long serialVersionUID = 2; -+import java.io.IOException; ++public class TorControlSyntaxError extends IOException { - public TorControlSyntaxError(String s) { super(s); } -+/** An exception raised when Tor behaves in an unexpected way. */ -+public class TorControlSyntaxError extends IOException { -+ -+ private static final long serialVersionUID = 2; -+ -+ public TorControlSyntaxError(String s) { -+ super(s); -+ } - } +-} ++ private static final long serialVersionUID = 3; ++ public TorControlSyntaxError(String s) { ++ super(s); ++ } ++}