diff --git a/apps/routerconsole/java/src/com/vuze/plugins/mlab/MLabRunner.java b/apps/routerconsole/java/src/com/vuze/plugins/mlab/MLabRunner.java
index 85abaa9bc40b80682fe40ef6d962289b102f49a1..2afb2c0e31097894dd2f1aff8210d507d353d07b 100644
--- a/apps/routerconsole/java/src/com/vuze/plugins/mlab/MLabRunner.java
+++ b/apps/routerconsole/java/src/com/vuze/plugins/mlab/MLabRunner.java
@@ -22,7 +22,6 @@ package com.vuze.plugins.mlab;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -49,9 +48,12 @@ import net.i2p.util.Log;
  */
 public class MLabRunner {
     // ns.measurementlab.net does not support https
-    // use ndt_ssl for test over ssl? but Tcpbw100 doesn't support it
     //private static final String NS_URL = "http://ns.measurementlab.net/ndt?format=json";
     private static final String NS_URL_SSL = "https://mlab-ns.appspot.com/ndt?format=json";
+    // use ndt_ssl for test over ssl
+    private static final String NS_URL_SSL_SSL = "https://mlab-ns.appspot.com/ndt_ssl?format=json";
+    private static final String PROP_SSL = "routerconsole.bwtest.useSSL";
+    private static final boolean DEFAULT_USE_SSL = true;
     private static final long NS_TIMEOUT = 20*1000;
     private final I2PAppContext _context;
     private final Log _log;
@@ -114,16 +116,20 @@ public class MLabRunner {
                         String server_host = null;
                         String server_city = null;
                         String server_country = null;
+                        boolean useSSL = _context.getProperty(PROP_SSL, DEFAULT_USE_SSL);
                         
                         try {
                             ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
+                            // http to name server
                             // public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort,
                             //               int numRetries, long minSize, long maxSize, String outputFile, OutputStream outputStream,
                             //               String url, boolean allowCaching, String etag, String postData) {
                             //EepGet eepget = new EepGet(_context, false, null, 0,
                             //                           0, 2, 1024, null, baos,
                             //                           NS_URL, false, null, null);
-                            EepGet eepget = new SSLEepGet(_context, baos, NS_URL_SSL);
+                            // https to name server
+                            String nsURL = useSSL ? NS_URL_SSL_SSL : NS_URL_SSL;
+                            EepGet eepget = new SSLEepGet(_context, baos, nsURL);
                             boolean ok = eepget.fetch(NS_TIMEOUT, NS_TIMEOUT, NS_TIMEOUT);
                             if (!ok)
                                 throw new IOException("ns fetch failed");
@@ -138,13 +144,12 @@ public class MLabRunner {
                             }
                             if (_log.shouldWarn())
                                 _log.warn("Got response: " + DataHelper.getUTF8(b));
-                            // TODO use IP instead to avoid another lookup?
-                            // or use "fqdn" in response instead of "url"
-                            URL url = new URL((String)map.get( "url" ));
-                            if (url == null) {
-                                throw new IOException("no url");
+                            // TODO use IP instead to avoid another lookup? - no, won't work with ssl
+                            // use "fqdn" in response instead of "url" since ndt_ssl does not have url
+                            server_host = (String)map.get("fqdn");
+                            if (server_host == null) {
+                                throw new IOException("no fqdn");
                             }
-                            server_host = url.getHost();
                             server_city = (String) map.get("city");
                             server_country = (String) map.get("country");
                             // ignore the returned port in the URL (7123) which is the applet, not the control port
@@ -158,12 +163,14 @@ public class MLabRunner {
                         if (server_host == null) {
                             // fallback to old, discouraged approach
                             server_host = "ndt.iupui.donar.measurement-lab.org";
+                            useSSL = false;
                             if (_log.shouldWarn())
                                 _log.warn("Failed to select server, falling back to donar method");
                         }
                         
+                        String[] args = useSSL ? new String[] { "-s", server_host } : new String[] { server_host };
                         long start = System.currentTimeMillis();
-                        final Tcpbw100 test = Tcpbw100.mainSupport( new String[]{ server_host });
+                        final Tcpbw100 test = Tcpbw100.mainSupport(args);
                         
                         run.addListener(
                             new ToolRunListener()
@@ -344,6 +351,8 @@ public class MLabRunner {
 
     /** standalone test */
     public static void main(String[] args) {
+        boolean useSSL = args.length > 0 && args[0].equals("-s");
+        System.setProperty(PROP_SSL, Boolean.toString(useSSL));
         I2PAppContext ctx = I2PAppContext.getGlobalContext();
         MLabRunner mlab = MLabRunner.getInstance(ctx);
         TestListener lsnr = new TestListener();
diff --git a/apps/routerconsole/java/src/edu/internet2/ndt/NDTConstants.java b/apps/routerconsole/java/src/edu/internet2/ndt/NDTConstants.java
index ddcae39e80f1089655e07eadb5a60918a03e2ef3..20342a244f4a7b36b9a8774b0158ff66184aa1ab 100644
--- a/apps/routerconsole/java/src/edu/internet2/ndt/NDTConstants.java
+++ b/apps/routerconsole/java/src/edu/internet2/ndt/NDTConstants.java
@@ -70,6 +70,7 @@ public class NDTConstants {
 
 	// NDT pre-fixed port ID
 	public static final int CONTROL_PORT_DEFAULT = 3001;
+	public static final int CONTROL_PORT_SSL = 3010;
 
 	// Section: SRV-QUEUE message status constants
 	public static final int SRV_QUEUE_TEST_STARTS_NOW = 0;
diff --git a/apps/routerconsole/java/src/edu/internet2/ndt/ResultsTextPane.java b/apps/routerconsole/java/src/edu/internet2/ndt/ResultsTextPane.java
index 5259bf9c944f0ef08edc969af8a7a3ef42729cc8..8683fb2d449396e30b16acd2f237c1a3c97497d8 100644
--- a/apps/routerconsole/java/src/edu/internet2/ndt/ResultsTextPane.java
+++ b/apps/routerconsole/java/src/edu/internet2/ndt/ResultsTextPane.java
@@ -25,16 +25,11 @@ public class ResultsTextPane extends JTextPane {
 	 *            String to be inserted into the document
 	 **/
 	public void append(String paramTextStr) {
-/****
 		try {
 			getStyledDocument().insertString(getStyledDocument().getLength(),
 					paramTextStr, null);
 		} catch (BadLocationException e) {
-			System.out
-					.println("WARNING: failed to append text to the text pane! ["
-							+ paramTextStr + "]");
 		}
-****/
 	}
 
 	/**
diff --git a/apps/routerconsole/java/src/edu/internet2/ndt/Tcpbw100.java b/apps/routerconsole/java/src/edu/internet2/ndt/Tcpbw100.java
index 0b7db6e0f561b7bbfa42938ddaa64842beef277b..bda625305c619fbdd012721b2fc90c8af063d9f7 100644
--- a/apps/routerconsole/java/src/edu/internet2/ndt/Tcpbw100.java
+++ b/apps/routerconsole/java/src/edu/internet2/ndt/Tcpbw100.java
@@ -89,8 +89,8 @@ import java.net.Socket;
 import java.net.SocketException;
 import java.net.URL;
 import java.net.UnknownHostException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
+import java.security.GeneralSecurityException;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.Locale;
 import java.util.ResourceBundle;
@@ -120,6 +120,7 @@ import com.vuze.plugins.mlab.tools.ndt.swingemu.*;
 import net.i2p.I2PAppContext;
 import net.i2p.util.Addresses;
 import net.i2p.util.I2PAppThread;
+import net.i2p.util.I2PSSLSocketFactory;
 import net.i2p.util.Log;
 
 /*
@@ -296,7 +297,22 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 
 	// I2P
 	private String _displayStatus = "";
-	private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(Tcpbw100.class);
+	private final I2PAppContext _context = I2PAppContext.getGlobalContext();
+	private final Log _log = _context.logManager().getLog(Tcpbw100.class);
+	private final boolean _useSSL;
+	private final I2PSSLSocketFactory _sslFactory;
+
+	public Tcpbw100(boolean useSSL) {
+		super();
+		I2PSSLSocketFactory sslFactory = null;
+		if (useSSL) {
+			try {
+		        	sslFactory = new I2PSSLSocketFactory(_context, true, "certificates/ndt");
+			} catch (GeneralSecurityException gse) { throw new IllegalStateException("init", gse); }
+		}
+		_sslFactory = sslFactory;
+		_useSSL = useSSL;
+	}
 
 	/**
 	 * public static void main for invoking as an Application
@@ -310,11 +326,14 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 	/** bigly */
 	public static Tcpbw100 mainSupport(String[] args) {
 		JFrame frame = new JFrame("ANL/Internet2 NDT (applet)");
+		boolean useSSL = args.length > 0 && args[0].equals("-s");
+		if (useSSL)
+			args = Arrays.copyOfRange(args, 1, args.length);
 		if (args.length < 1 || args.length > 2) {
-			System.out.println("Usage: java -jar Tcpbw100.jar <hostname> [client-id]");
+			System.out.println("Usage: java -jar Tcpbw100.jar [-s] <hostname> [client-id]");
 			System.exit(0);
 		}
-		final Tcpbw100 applet = new Tcpbw100();
+		final Tcpbw100 applet = new Tcpbw100(useSSL);
 		frame.addWindowListener(new WindowAdapter() {
 			public void windowClosing(WindowEvent e) {
 				applet.destroy();
@@ -748,8 +767,6 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 						}
 					}
 				} catch (Exception e) {
-					_log.warn("?", e);
-
 					String sMessage = NDTUtils.isEmpty(e.getMessage())
 							? _resBundDisplayMsgs.getString("withoutMessage")
 							: e.getMessage();
@@ -758,6 +775,7 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 					_sErrMsg = _resBundDisplayMsgs.getString("unexpectedException")
 							+ " (" + e.getClass().getName() + "): "
 							+ sMessage + "\n";
+					_log.warn(_sErrMsg, e);
 				}
 
 				// If test failed due to any reason, mark failure reason too
@@ -808,7 +826,7 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 		}
 
 		try {
-			String lang = I2PAppContext.getGlobalContext().getProperty("routerconsole.lang");
+			String lang = _context.getProperty("routerconsole.lang");
 			if (lang != null) {
 				_localeObj = new Locale(lang);
 				_sLang = lang;
@@ -826,7 +844,7 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 		} catch (Exception e) {
 			JOptionPane.showMessageDialog(null,
 					"Error while loading language files:\n" + e.getMessage());
-			_log.warn("?", e);
+			_log.warn("bundle", e);
 		}
 
 		createMainWindow();
@@ -1237,8 +1255,6 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 
 				getAppletContext().showDocument(_targetURL);
 			} catch (Exception e) {
-				_log.warn("?", e);
-
 				String sMessage = NDTUtils.isEmpty(e.getMessage())
 						? _resBundDisplayMsgs.getString("withoutMessage")
 						: e.getMessage();
@@ -1247,6 +1263,7 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 						+ " (" + e.getClass().getName() + "): "
 						+ sMessage + "\n";
 
+				_log.warn(_sErrMsg, e);
 				_resultsTxtPane.append(_sErrMsg);
 			}
 		} // end mail-to functionality
@@ -1282,7 +1299,8 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 		synchronized(this) {
 			_displayStatus = msg;
 		}
-		_log.warn("NDT STATUS: " + msg);
+		if (_log.shouldWarn())
+		    _log.warn("NDT STATUS: " + msg);
 	}
 
 	/**
@@ -1358,6 +1376,7 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 			// connect to server using port obtained above
 			Socket midSrvrSockObj = null;
 			try {
+				// this one is NOT SSL
 				midSrvrSockObj = new Socket(hostAddress, midport);
 			} catch (UnknownHostException e) {
 				_log.warn("Don't know about host: " + sHostName, e);
@@ -1641,9 +1660,9 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 				srvSocket = new ServerSocket(
 						NDTConstants.SOCKET_FREE_PORT_INDICATOR);
 			} catch (Exception e) {
-				_log.warn("?", e);
 				_sErrMsg = _resBundDisplayMsgs.getString("sfwSocketFail")
 						+ "\n";
+				_log.warn(_sErrMsg, e);
 				return true;
 			}
 
@@ -1680,6 +1699,7 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 
 			// Now, run Test from client for the C->S direction SFW test
 			// trying to connect to ephemeral port number sent by server
+			// this one is NOT SSL
 			Socket sfwSocket = new Socket();
 			try {
 				// create socket to ephemeral port. testTime now specified in mS
@@ -1693,7 +1713,7 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 				sfwCtl.send_json_msg(MessageType.TEST_MSG, new String(
 						NDTConstants.SFW_PREDEFINED_TEST_MESSAGE).getBytes());
 			} catch (Exception e) {
-				_log.warn("?", e);
+				_log.warn("sfwSocket", e);
 				//Indication that there might be a firewall from C->S side.
 			}
 
@@ -1819,7 +1839,7 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 			// client connects to this port
 			final Socket outSocket;
 			try {
-				outSocket = new Socket(hostAddress, iC2sport);
+				outSocket = newSocket(hostAddress, iC2sport);
 			} catch (UnknownHostException e) {
 				_log.warn("Don't know about host: " + sHostName, e);
 				_sErrMsg = _resBundDisplayMsgs.getString("unknownServer")
@@ -1917,7 +1937,8 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 				try {
 					outStream.write(_yabuff2Write, 0, _yabuff2Write.length);
 				} catch (SocketException e) {
-					_log.warn("SocketException while writing to server", e);
+					// normal after 10 seconds
+					_log.debug("SocketException while writing to server (normal)", e);
 					break;
 				}
 				// catch (InterruptedIOException iioe) {
@@ -2084,7 +2105,7 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 			// Create socket and bind to port as instructed by server
 			Socket inSocket;
 			try {
-				inSocket = new Socket(hostAddress, iS2cport);
+				inSocket = newSocket(hostAddress, iS2cport);
 			} catch (UnknownHostException e) {
 				_log.warn("Don't know about host: " + sHostName, e);
 				_sErrMsg = "unknown server\n";
@@ -2202,9 +2223,9 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 					_iSsndqueue = Integer.parseInt(JSONUtils.getValueFromJsonObj(tmpstr3, "UnsentDataAmount"));
 					_dSbytes = Double.parseDouble(JSONUtils.getValueFromJsonObj(tmpstr3, "TotalSentByte"));
 				} catch (Exception e) {
-					_log.warn("?", e);
 					_sErrMsg = _resBundDisplayMsgs.getString("inboundWrongMessage")
 							+ "\n";
+					_log.warn(_sErrMsg, e);
 					return true;
 				}
 			}
@@ -2220,9 +2241,9 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 					_dSbytes = Double.parseDouble(tmpstr3.substring(k1 + 1)
 							.substring(k2 + 1));
 				} catch (Exception e) {
-					_log.warn("?", e);
 					_sErrMsg = _resBundDisplayMsgs.getString("inboundWrongMessage")
 							+ "\n";
+					_log.warn(_sErrMsg, e);
 					return true;
 				}
 			}
@@ -2497,7 +2518,7 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 		// The default control port used for the NDT tests session. NDT server
 		// listens
 		// to this port
-		int ctlport = NDTConstants.CONTROL_PORT_DEFAULT;
+		int ctlport = _useSSL ? NDTConstants.CONTROL_PORT_SSL : NDTConstants.CONTROL_PORT_DEFAULT;
 
 		// Commenting these 2 variables - seem unused
 		// double wait2;
@@ -2521,7 +2542,7 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 					+ "] "
 					+ _resBundDisplayMsgs.getString("toRunTest") + "\n");
 			// create socket to host specified by user and the default port
-			ctlSocket = new Socket(hostAddress, ctlport);
+			ctlSocket = newSocket(hostAddress, ctlport);
 		} catch (UnknownHostException e) {
 			_log.warn("Don't know about host: " + sHostName, e);
 			_sErrMsg = _resBundDisplayMsgs.getString("unknownServer") + "\n";
@@ -2565,6 +2586,7 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 			_sErrMsg = _resBundDisplayMsgs.getString("unsupportedClient")
 					+ "\n";
 			_bFailed = true;
+			try { ctlSocket.close(); } catch (IOException ioe) {}
 			return;
 		}
 
@@ -2597,7 +2619,11 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 								.getString("unsupportedMsgExtendedLogin")
 								+ "\n");
 						// create socket to host specified by user and the default port
-						ctlSocket = new Socket(hostAddress, ctlport);
+						// we seem to always get here, why bother trying extended above?
+						if (ctlSocket != null) {
+							try { ctlSocket.close(); } catch (IOException ioe) {}
+						}
+						ctlSocket = newSocket(hostAddress, ctlport);
 					} catch (UnknownHostException e) {
 						_log.warn("Don't know about host: " + sHostName, e);
 						_sErrMsg = _resBundDisplayMsgs.getString("unknownServer") + "\n";
@@ -2808,6 +2834,9 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 		// cannot be successfully run,
 		// indicate reason
 		while (tokenizer.hasMoreTokens()) {
+		    // None of test_xxx catch NumberFormatException,
+		    // do it here so we don't kill the whole thing
+		    try {
 			if (sPanel.wantToStop()) { // user has indicated decision to stop
 										// tests from GUI
 				protocolObj.send_json_msg(MessageType.MSG_ERROR,
@@ -2871,6 +2900,11 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 				_bFailed = true;
 				return;
 			}
+		    } catch (NumberFormatException nfe) {
+			// None of test_xxx catch NumberFormatException,
+			// do it here so we don't kill the whole thing
+			_log.warn("nfe", nfe);
+		    }
 		}
 
 		if (sPanel.wantToStop()) { // user has indicated decision to stop tests
@@ -2973,6 +3007,25 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 		pub_status = "done";
 	}
 
+	/**
+	 *  Return a SSL or standard socket depending on config
+	 */
+	private Socket newSocket(InetAddress hostAddress, int ctlPort) throws IOException {
+		if (_log.shouldInfo())
+			_log.info("Connecting to " + hostAddress + ':' + ctlPort, new Exception("I did it"));
+		Socket rv;
+		if (_useSSL) {
+			rv = _sslFactory.createSocket(hostAddress, ctlPort);
+			if (_log.shouldWarn())
+				_log.warn("New SSL socket to " + hostAddress + ':' + ctlPort);
+		} else {
+			rv = new Socket(hostAddress, ctlPort);
+			if (_log.shouldWarn())
+				_log.warn("New non-SSL socket to " + hostAddress + ':' + ctlPort);
+		}
+		return rv;
+	}
+
 	/**
 	 * Method that interprets test results. This routine extracts the key-value
 	 * pairs of results of various categories and assigns these to the correct
@@ -4439,10 +4492,15 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 	 * @return {int} The parsed value.
 	 */
 	private int parseMsgBodyToInt(String msg, int radix) {
-		if (jsonSupport) {
-			return Integer.parseInt(JSONUtils.getSingleMessage(msg), radix);
-		} else {
-			return Integer.parseInt(msg, radix);
+		try {
+			if (jsonSupport) {
+				return Integer.parseInt(JSONUtils.getSingleMessage(msg), radix);
+			} else {
+				return Integer.parseInt(msg, radix);
+			}
+		} catch (NumberFormatException nfe) {
+			_log.warn("parse", nfe);
+			return 0;
 		}
 	}
 
@@ -4469,7 +4527,7 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 					thread_group.destroy();
 					break;
 				}catch( Throwable e ){
-					_log.warn("?", e);
+					_log.warn("TG", e);
 				}
 			}
 			
@@ -4495,7 +4553,7 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 					Thread t, 
 					Throwable e) 
 				{
-					_log.debug("?", e);
+					_log.warn("TG", e);
 				}
 			};
 		
@@ -4515,7 +4573,7 @@ public class Tcpbw100 extends JApplet implements ActionListener {
 						}catch( Throwable e ){
 						
 							if ( !( e instanceof ThreadDeath )){
-								_log.debug("?", e);
+								_log.warn("TG", e);
 							}
 						}finally{
 							//sem.release();