fixing sh*t I broke due to strange Android build process (re-adding src files)
svn:r21068
This commit is contained in:
parent
1b587ab9d1
commit
64b7089f93
|
@ -0,0 +1,639 @@
|
|||
package org.torproject.android;
|
||||
/* <!-- in case someone opens this in a browser... --> <pre> */
|
||||
/*
|
||||
* This is a simple multi-threaded Java proxy server
|
||||
* for HTTP requests (HTTPS doesn't seem to work, because
|
||||
* the CONNECT requests aren't always handled properly).
|
||||
* I implemented the class as a thread so you can call it
|
||||
* from other programs and kill it, if necessary (by using
|
||||
* the closeSocket() method).
|
||||
*
|
||||
* We'll call this the 1.1 version of this class. All I
|
||||
* changed was to separate the HTTP header elements with
|
||||
* \r\n instead of just \n, to comply with the official
|
||||
* HTTP specification.
|
||||
*
|
||||
* This can be used either as a direct proxy to other
|
||||
* servers, or as a forwarding proxy to another proxy
|
||||
* server. This makes it useful if you want to monitor
|
||||
* traffic going to and from a proxy server (for example,
|
||||
* you can run this on your local machine and set the
|
||||
* fwdServer and fwdPort to a real proxy server, and then
|
||||
* tell your browser to use "localhost" as the proxy, and
|
||||
* you can watch the browser traffic going in and out).
|
||||
*
|
||||
* One limitation of this implementation is that it doesn't
|
||||
* close the ProxyThread socket if the client disconnects
|
||||
* or the server never responds, so you could end up with
|
||||
* a bunch of loose threads running amuck and waiting for
|
||||
* connections. As a band-aid, you can set the server socket
|
||||
* to timeout after a certain amount of time (use the
|
||||
* setTimeout() method in the ProxyThread class), although
|
||||
* this can cause false timeouts if a remote server is simply
|
||||
* slow to respond.
|
||||
*
|
||||
* Another thing is that it doesn't limit the number of
|
||||
* socket threads it will create, so if you use this on a
|
||||
* really busy machine that processed a bunch of requests,
|
||||
* you may have problems. You should use thread pools if
|
||||
* you're going to try something like this in a "real"
|
||||
* application.
|
||||
*
|
||||
* Note that if you're using the "main" method to run this
|
||||
* by itself and you don't need the debug output, it will
|
||||
* run a bit faster if you pipe the std output to 'nul'.
|
||||
*
|
||||
* You may use this code as you wish, just don't pretend
|
||||
* that you wrote it yourself, and don't hold me liable for
|
||||
* anything that it does or doesn't do. If you're feeling
|
||||
* especially honest, please include a link to nsftools.com
|
||||
* along with the code. Thanks, and good luck.
|
||||
*
|
||||
* Julian Robichaux -- http://www.nsftools.com
|
||||
*/
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.Array;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import net.sourceforge.jsocks.socks.Socks5Proxy;
|
||||
import net.sourceforge.jsocks.socks.SocksSocket;
|
||||
|
||||
|
||||
public class HttpProxy extends Thread
|
||||
{
|
||||
public static final int DEFAULT_PORT = 8888;
|
||||
|
||||
private ServerSocket server = null;
|
||||
private int thisPort = DEFAULT_PORT;
|
||||
private String fwdServer = "";
|
||||
private int fwdPort = 0;
|
||||
private int ptTimeout = ProxyThread.DEFAULT_TIMEOUT;
|
||||
private int debugLevel = 1;
|
||||
private PrintStream debugOut = System.out;
|
||||
private boolean keepRunning = true;
|
||||
private boolean doSocks = false;
|
||||
|
||||
private Socks5Proxy sProxy = null;
|
||||
|
||||
/**
|
||||
* @return the doSocks
|
||||
*/
|
||||
public boolean isDoSocks() {
|
||||
return doSocks;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param doSocks the doSocks to set
|
||||
*/
|
||||
public void setDoSocks(boolean doSocks) {
|
||||
this.doSocks = doSocks;
|
||||
}
|
||||
|
||||
|
||||
/* here's a main method, in case you want to run this by itself */
|
||||
public static void main (String args[])
|
||||
{
|
||||
int port = 0;
|
||||
String fwdProxyServer = "";
|
||||
int fwdProxyPort = 0;
|
||||
|
||||
if (args.length == 0)
|
||||
{
|
||||
System.err.println("USAGE: java jProxy <port number> [<fwd proxy> <fwd port>]");
|
||||
System.err.println(" <port number> the port this service listens on");
|
||||
System.err.println(" <fwd proxy> optional proxy server to forward requests to");
|
||||
System.err.println(" <fwd port> the port that the optional proxy server is on");
|
||||
System.err.println("\nHINT: if you don't want to see all the debug information flying by,");
|
||||
System.err.println("you can pipe the output to a file or to 'nul' using \">\". For example:");
|
||||
System.err.println(" to send output to the file prox.txt: java jProxy 8080 > prox.txt");
|
||||
System.err.println(" to make the output go away: java jProxy 8080 > nul");
|
||||
return;
|
||||
}
|
||||
|
||||
// get the command-line parameters
|
||||
port = Integer.parseInt(args[0]);
|
||||
if (args.length > 2)
|
||||
{
|
||||
fwdProxyServer = args[1];
|
||||
fwdProxyPort = Integer.parseInt(args[2]);
|
||||
}
|
||||
|
||||
// create and start the jProxy thread, using a 20 second timeout
|
||||
// value to keep the threads from piling up too much
|
||||
System.err.println(" ** Starting jProxy on port " + port + ". Press CTRL-C to end. **\n");
|
||||
HttpProxy jp = new HttpProxy(port, fwdProxyServer, fwdProxyPort, 20);
|
||||
jp.setDebug(1, System.out); // or set the debug level to 2 for tons of output
|
||||
jp.start();
|
||||
|
||||
// run forever; if you were calling this class from another
|
||||
// program and you wanted to stop the jProxy thread at some
|
||||
// point, you could write a loop that waits for a certain
|
||||
// condition and then calls jProxy.closeSocket() to kill
|
||||
// the running jProxy thread
|
||||
while (true)
|
||||
{
|
||||
try { Thread.sleep(3000); } catch (Exception e) {}
|
||||
}
|
||||
|
||||
// if we ever had a condition that stopped the loop above,
|
||||
// we'd want to do this to kill the running thread
|
||||
//jp.closeSocket();
|
||||
//return;
|
||||
}
|
||||
|
||||
|
||||
/* the proxy server just listens for connections and creates
|
||||
* a new thread for each connection attempt (the ProxyThread
|
||||
* class really does all the work)
|
||||
*/
|
||||
public HttpProxy (int port)
|
||||
{
|
||||
thisPort = port;
|
||||
|
||||
try {
|
||||
sProxy = new Socks5Proxy(TorConstants.IP_LOCALHOST,TorConstants.PORT_SOCKS);
|
||||
} catch (UnknownHostException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
sProxy.resolveAddrLocally(false);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public HttpProxy (int port, String proxyServer, int proxyPort)
|
||||
{
|
||||
thisPort = port;
|
||||
fwdServer = proxyServer;
|
||||
fwdPort = proxyPort;
|
||||
}
|
||||
|
||||
public HttpProxy (int port, String proxyServer, int proxyPort, int timeout)
|
||||
{
|
||||
thisPort = port;
|
||||
fwdServer = proxyServer;
|
||||
fwdPort = proxyPort;
|
||||
ptTimeout = timeout;
|
||||
}
|
||||
|
||||
|
||||
/* allow the user to decide whether or not to send debug
|
||||
* output to the console or some other PrintStream
|
||||
*/
|
||||
public void setDebug (int level, PrintStream out)
|
||||
{
|
||||
debugLevel = level;
|
||||
debugOut = out;
|
||||
}
|
||||
|
||||
|
||||
/* get the port that we're supposed to be listening on
|
||||
*/
|
||||
public int getPort ()
|
||||
{
|
||||
return thisPort;
|
||||
}
|
||||
|
||||
|
||||
/* return whether or not the socket is currently open
|
||||
*/
|
||||
public boolean isRunning ()
|
||||
{
|
||||
if (server == null)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* closeSocket will close the open ServerSocket; use this
|
||||
* to halt a running jProxy thread
|
||||
*/
|
||||
public void closeSocket ()
|
||||
{
|
||||
try {
|
||||
keepRunning = false;
|
||||
// close the open server socket
|
||||
server.close();
|
||||
// send it a message to make it stop waiting immediately
|
||||
// (not really necessary)
|
||||
/*Socket s = new Socket("localhost", thisPort);
|
||||
OutputStream os = s.getOutputStream();
|
||||
os.write((byte)0);
|
||||
os.close();
|
||||
s.close();*/
|
||||
} catch(Exception e) {
|
||||
if (debugLevel > 0)
|
||||
debugOut.println(e);
|
||||
}
|
||||
|
||||
server = null;
|
||||
}
|
||||
|
||||
|
||||
public void run()
|
||||
{
|
||||
try {
|
||||
// create a server socket, and loop forever listening for
|
||||
// client connections
|
||||
server = new ServerSocket(thisPort);
|
||||
|
||||
while (keepRunning)
|
||||
{
|
||||
Socket client = server.accept();
|
||||
ProxyThread t = new ProxyThread(client, doSocks, sProxy);
|
||||
//t.setDebug(debugLevel, debugOut);
|
||||
//t.setTimeout(ptTimeout);
|
||||
t.start();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (debugLevel > 0)
|
||||
debugOut.println("jProxy Thread error: " + e);
|
||||
}
|
||||
|
||||
closeSocket();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The ProxyThread will take an HTTP request from the client
|
||||
* socket and send it to either the server that the client is
|
||||
* trying to contact, or another proxy server
|
||||
*/
|
||||
class ProxyThread extends Thread
|
||||
{
|
||||
private Socket pSocket;
|
||||
private String fwdServer = "";
|
||||
private int fwdPort = 0;
|
||||
private int debugLevel = 0;
|
||||
private PrintStream debugOut = System.out;
|
||||
|
||||
// the socketTimeout is used to time out the connection to
|
||||
// the remote server after a certain period of inactivity;
|
||||
// the value is in milliseconds -- use zero if you don't want
|
||||
// a timeout
|
||||
public static final int DEFAULT_TIMEOUT = 20 * 1000;
|
||||
private int socketTimeout = DEFAULT_TIMEOUT;
|
||||
|
||||
private boolean doSocks = false;
|
||||
|
||||
private static Socks5Proxy sProxy = null;
|
||||
|
||||
public ProxyThread(Socket s, boolean doSocks, Socks5Proxy sProxy)
|
||||
{
|
||||
pSocket = s;
|
||||
|
||||
this.sProxy = sProxy;
|
||||
this.doSocks = doSocks;
|
||||
}
|
||||
|
||||
public ProxyThread(Socket s, String proxy, int port)
|
||||
{
|
||||
pSocket = s;
|
||||
fwdServer = proxy;
|
||||
fwdPort = port;
|
||||
}
|
||||
|
||||
|
||||
public void setTimeout (int timeout)
|
||||
{
|
||||
// assume that the user will pass the timeout value
|
||||
// in seconds (because that's just more intuitive)
|
||||
socketTimeout = timeout * 1000;
|
||||
}
|
||||
|
||||
|
||||
public void setDebug (int level, PrintStream out)
|
||||
{
|
||||
debugLevel = level;
|
||||
debugOut = out;
|
||||
}
|
||||
|
||||
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
// client streams (make sure you're using streams that use
|
||||
// byte arrays, so things like GIF and JPEG files and file
|
||||
// downloads will transfer properly)
|
||||
BufferedInputStream clientIn = new BufferedInputStream(pSocket.getInputStream());
|
||||
BufferedOutputStream clientOut = new BufferedOutputStream(pSocket.getOutputStream());
|
||||
|
||||
// the socket to the remote server
|
||||
Socket server = null;
|
||||
|
||||
// other variables
|
||||
byte[] request = null;
|
||||
byte[] response = null;
|
||||
int requestLength = 0;
|
||||
int responseLength = 0;
|
||||
int pos = -1;
|
||||
StringBuffer host = new StringBuffer("");
|
||||
String hostName = "";
|
||||
int hostPort = 80;
|
||||
|
||||
// get the header info (the web browser won't disconnect after
|
||||
// it's sent a request, so make sure the waitForDisconnect
|
||||
// parameter is false)
|
||||
request = getHTTPData(clientIn, host, false);
|
||||
requestLength = Array.getLength(request);
|
||||
|
||||
// separate the host name from the host port, if necessary
|
||||
// (like if it's "servername:8000")
|
||||
hostName = host.toString();
|
||||
pos = hostName.indexOf(":");
|
||||
if (pos > 0)
|
||||
{
|
||||
try { hostPort = Integer.parseInt(hostName.substring(pos + 1));
|
||||
} catch (Exception e) { }
|
||||
hostName = hostName.substring(0, pos);
|
||||
}
|
||||
|
||||
// either forward this request to another proxy server or
|
||||
// send it straight to the Host
|
||||
try
|
||||
{
|
||||
|
||||
if (!doSocks)
|
||||
{
|
||||
if ((fwdServer.length() > 0) && (fwdPort > 0))
|
||||
{
|
||||
server = new Socket(fwdServer, fwdPort);
|
||||
} else {
|
||||
server = new Socket(hostName, hostPort);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
server = new SocksSocket(sProxy,hostName, hostPort);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
// tell the client there was an error
|
||||
String errMsg = "HTTP/1.0 500\nContent Type: text/plain\n\n" +
|
||||
"Error connecting to the server:\n" + e + "\n";
|
||||
clientOut.write(errMsg.getBytes(), 0, errMsg.length());
|
||||
}
|
||||
|
||||
if (server != null)
|
||||
{
|
||||
server.setSoTimeout(socketTimeout);
|
||||
BufferedInputStream serverIn = new BufferedInputStream(server.getInputStream());
|
||||
BufferedOutputStream serverOut = new BufferedOutputStream(server.getOutputStream());
|
||||
|
||||
// send the request out
|
||||
serverOut.write(request, 0, requestLength);
|
||||
serverOut.flush();
|
||||
|
||||
// and get the response; if we're not at a debug level that
|
||||
// requires us to return the data in the response, just stream
|
||||
// it back to the client to save ourselves from having to
|
||||
// create and destroy an unnecessary byte array. Also, we
|
||||
// should set the waitForDisconnect parameter to 'true',
|
||||
// because some servers (like Google) don't always set the
|
||||
// Content-Length header field, so we have to listen until
|
||||
// they decide to disconnect (or the connection times out).
|
||||
if (debugLevel > 1)
|
||||
{
|
||||
response = getHTTPData(serverIn, true);
|
||||
responseLength = Array.getLength(response);
|
||||
} else {
|
||||
responseLength = streamHTTPData(serverIn, clientOut, true);
|
||||
}
|
||||
|
||||
serverIn.close();
|
||||
serverOut.close();
|
||||
}
|
||||
|
||||
// send the response back to the client, if we haven't already
|
||||
if (debugLevel > 1)
|
||||
clientOut.write(response, 0, responseLength);
|
||||
|
||||
// if the user wants debug info, send them debug info; however,
|
||||
// keep in mind that because we're using threads, the output won't
|
||||
// necessarily be synchronous
|
||||
if (debugLevel > 0)
|
||||
{
|
||||
long endTime = System.currentTimeMillis();
|
||||
debugOut.println("Request from " + pSocket.getInetAddress().getHostAddress() +
|
||||
" on Port " + pSocket.getLocalPort() +
|
||||
" to host " + hostName + ":" + hostPort +
|
||||
"\n (" + requestLength + " bytes sent, " +
|
||||
responseLength + " bytes returned, " +
|
||||
Long.toString(endTime - startTime) + " ms elapsed)");
|
||||
debugOut.flush();
|
||||
}
|
||||
if (debugLevel > 1)
|
||||
{
|
||||
debugOut.println("REQUEST:\n" + (new String(request)));
|
||||
debugOut.println("RESPONSE:\n" + (new String(response)));
|
||||
debugOut.flush();
|
||||
}
|
||||
|
||||
// close all the client streams so we can listen again
|
||||
clientOut.close();
|
||||
clientIn.close();
|
||||
pSocket.close();
|
||||
} catch (Exception e) {
|
||||
if (debugLevel > 0)
|
||||
debugOut.println("Error in ProxyThread: " + e);
|
||||
//e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private byte[] getHTTPData (InputStream in, boolean waitForDisconnect)
|
||||
{
|
||||
// get the HTTP data from an InputStream, and return it as
|
||||
// a byte array
|
||||
// the waitForDisconnect parameter tells us what to do in case
|
||||
// the HTTP header doesn't specify the Content-Length of the
|
||||
// transmission
|
||||
StringBuffer foo = new StringBuffer("");
|
||||
return getHTTPData(in, foo, waitForDisconnect);
|
||||
}
|
||||
|
||||
|
||||
private byte[] getHTTPData (InputStream in, StringBuffer host, boolean waitForDisconnect)
|
||||
{
|
||||
// get the HTTP data from an InputStream, and return it as
|
||||
// a byte array, and also return the Host entry in the header,
|
||||
// if it's specified -- note that we have to use a StringBuffer
|
||||
// for the 'host' variable, because a String won't return any
|
||||
// information when it's used as a parameter like that
|
||||
ByteArrayOutputStream bs = new ByteArrayOutputStream();
|
||||
streamHTTPData(in, bs, host, waitForDisconnect);
|
||||
return bs.toByteArray();
|
||||
}
|
||||
|
||||
|
||||
private int streamHTTPData (InputStream in, OutputStream out, boolean waitForDisconnect)
|
||||
{
|
||||
StringBuffer foo = new StringBuffer("");
|
||||
return streamHTTPData(in, out, foo, waitForDisconnect);
|
||||
}
|
||||
|
||||
private int streamHTTPData (InputStream in, OutputStream out,
|
||||
StringBuffer host, boolean waitForDisconnect)
|
||||
{
|
||||
// get the HTTP data from an InputStream, and send it to
|
||||
// the designated OutputStream
|
||||
StringBuffer header = new StringBuffer("");
|
||||
String data = "";
|
||||
int responseCode = 200;
|
||||
int contentLength = 0;
|
||||
int pos = -1;
|
||||
int byteCount = 0;
|
||||
|
||||
try
|
||||
{
|
||||
// get the first line of the header, so we know the response code
|
||||
data = readLine(in);
|
||||
if (data != null)
|
||||
{
|
||||
header.append(data + "\r\n");
|
||||
pos = data.indexOf(" ");
|
||||
if ((data.toLowerCase().startsWith("http")) &&
|
||||
(pos >= 0) && (data.indexOf(" ", pos+1) >= 0))
|
||||
{
|
||||
String rcString = data.substring(pos+1, data.indexOf(" ", pos+1));
|
||||
try
|
||||
{
|
||||
responseCode = Integer.parseInt(rcString);
|
||||
} catch (Exception e) {
|
||||
if (debugLevel > 0)
|
||||
debugOut.println("Error parsing response code " + rcString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get the rest of the header info
|
||||
while ((data = readLine(in)) != null)
|
||||
{
|
||||
// the header ends at the first blank line
|
||||
if (data.length() == 0)
|
||||
break;
|
||||
header.append(data + "\r\n");
|
||||
|
||||
// check for the Host header
|
||||
pos = data.toLowerCase().indexOf("host:");
|
||||
if (pos >= 0)
|
||||
{
|
||||
host.setLength(0);
|
||||
host.append(data.substring(pos + 5).trim());
|
||||
}
|
||||
|
||||
// check for the Content-Length header
|
||||
pos = data.toLowerCase().indexOf("content-length:");
|
||||
if (pos >= 0)
|
||||
contentLength = Integer.parseInt(data.substring(pos + 15).trim());
|
||||
}
|
||||
|
||||
// add a blank line to terminate the header info
|
||||
header.append("\r\n");
|
||||
|
||||
// convert the header to a byte array, and write it to our stream
|
||||
out.write(header.toString().getBytes(), 0, header.length());
|
||||
|
||||
// if the header indicated that this was not a 200 response,
|
||||
// just return what we've got if there is no Content-Length,
|
||||
// because we may not be getting anything else
|
||||
if ((responseCode != 200) && (contentLength == 0))
|
||||
{
|
||||
out.flush();
|
||||
return header.length();
|
||||
}
|
||||
|
||||
// get the body, if any; we try to use the Content-Length header to
|
||||
// determine how much data we're supposed to be getting, because
|
||||
// sometimes the client/server won't disconnect after sending us
|
||||
// information...
|
||||
if (contentLength > 0)
|
||||
waitForDisconnect = false;
|
||||
|
||||
if ((contentLength > 0) || (waitForDisconnect))
|
||||
{
|
||||
try {
|
||||
byte[] buf = new byte[4096];
|
||||
int bytesIn = 0;
|
||||
while ( ((byteCount < contentLength) || (waitForDisconnect))
|
||||
&& ((bytesIn = in.read(buf)) >= 0) )
|
||||
{
|
||||
out.write(buf, 0, bytesIn);
|
||||
byteCount += bytesIn;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
String errMsg = "Error getting HTTP body: " + e;
|
||||
if (debugLevel > 0)
|
||||
debugOut.println(errMsg);
|
||||
//bs.write(errMsg.getBytes(), 0, errMsg.length());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (debugLevel > 0)
|
||||
debugOut.println("Error getting HTTP data: " + e);
|
||||
}
|
||||
|
||||
//flush the OutputStream and return
|
||||
try { out.flush(); } catch (Exception e) {}
|
||||
return (header.length() + byteCount);
|
||||
}
|
||||
|
||||
|
||||
private String readLine (InputStream in)
|
||||
{
|
||||
// reads a line of text from an InputStream
|
||||
StringBuffer data = new StringBuffer("");
|
||||
int c;
|
||||
|
||||
try
|
||||
{
|
||||
// if we have nothing to read, just return null
|
||||
in.mark(1);
|
||||
if (in.read() == -1)
|
||||
return null;
|
||||
else
|
||||
in.reset();
|
||||
|
||||
while ((c = in.read()) >= 0)
|
||||
{
|
||||
// check for an end-of-line character
|
||||
if ((c == 0) || (c == 10) || (c == 13))
|
||||
break;
|
||||
else
|
||||
data.append((char)c);
|
||||
}
|
||||
|
||||
// deal with the case where the end-of-line terminator is \r\n
|
||||
if (c == 13)
|
||||
{
|
||||
in.mark(1);
|
||||
if (in.read() != 10)
|
||||
in.reset();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (debugLevel > 0)
|
||||
debugOut.println("Error getting header: " + e);
|
||||
}
|
||||
|
||||
// and return what we have
|
||||
return data.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
/* Copyright (c) 2009, Nathan Freitas, The Guardian Project - http://openideals.com/guardian */
|
||||
/* See LICENSE for licensing information */
|
||||
/** SOCKS aware echo client*/
|
||||
|
||||
package org.torproject.android;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import net.sourceforge.jsocks.socks.*;
|
||||
|
||||
|
||||
public class SocksClient implements Runnable {
|
||||
|
||||
private int port;
|
||||
private InetAddress hostIP;
|
||||
|
||||
private Socket ss;
|
||||
private InputStream in;
|
||||
private OutputStream out;
|
||||
|
||||
private static final int BUF_SIZE = 1024;
|
||||
|
||||
public SocksClient(String host,int port)
|
||||
throws IOException,UnknownHostException,SocksException{
|
||||
this.port = port;
|
||||
|
||||
ss = new SocksSocket(host, port);
|
||||
out = ss.getOutputStream();
|
||||
in = ss.getInputStream();
|
||||
System.out.println("Connected...");
|
||||
System.out.println("TO: "+host+":"+port);
|
||||
System.out.println("ViaProxy: "+ss.getLocalAddress().getHostAddress()
|
||||
+":"+ss.getLocalPort());
|
||||
|
||||
}
|
||||
|
||||
public void close()throws IOException{
|
||||
ss.close();
|
||||
}
|
||||
public void send(String s) throws IOException{
|
||||
out.write(s.getBytes());
|
||||
}
|
||||
|
||||
public void run(){
|
||||
byte[] buf = new byte[1024];
|
||||
int bytes_read;
|
||||
try{
|
||||
while((bytes_read = in.read(buf)) > 0){
|
||||
System.out.write(buf,0,bytes_read);
|
||||
}
|
||||
}catch(IOException io_ex){
|
||||
io_ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void usage(){
|
||||
System.err.print(
|
||||
"Usage: java SocksTest host port [socksHost socksPort]\n");
|
||||
}
|
||||
|
||||
|
||||
public static void main(String args[]){
|
||||
int port;
|
||||
String host;
|
||||
int proxyPort;
|
||||
String proxyHost;
|
||||
|
||||
if(args.length > 1 && args.length < 5){
|
||||
try{
|
||||
|
||||
host = args[0];
|
||||
port = Integer.parseInt(args[1]);
|
||||
|
||||
proxyPort =(args.length > 3)? Integer.parseInt(args[3])
|
||||
: TorConstants.PORT_SOCKS;
|
||||
|
||||
host = args[0];
|
||||
proxyHost =(args.length > 2)? args[2]
|
||||
: TorConstants.IP_LOCALHOST;
|
||||
|
||||
Proxy.setDefaultProxy(proxyHost,proxyPort,"KOUKY001");
|
||||
//Proxy.setDefaultProxy(proxyHost,proxyPort);
|
||||
InetRange inetRange = new InetRange();
|
||||
inetRange.add(InetAddress.getByName("localhost"));
|
||||
Proxy.getDefaultProxy().setDirect(inetRange);
|
||||
|
||||
|
||||
SocksClient st = new SocksClient(host,port);
|
||||
Thread thread = new Thread(st);
|
||||
thread.start();
|
||||
|
||||
BufferedReader in = new BufferedReader(
|
||||
new InputStreamReader(System.in));
|
||||
String s;
|
||||
|
||||
s = in.readLine();
|
||||
while(s != null){
|
||||
st.send(s+"\r\n");
|
||||
//try{
|
||||
//Thread.currentThread().sleep(10);
|
||||
//}catch(InterruptedException i_ex){
|
||||
//}
|
||||
s = in.readLine();
|
||||
}
|
||||
st.close();
|
||||
System.exit(1);
|
||||
|
||||
}catch(SocksException s_ex){
|
||||
System.err.println("SocksException:"+s_ex);
|
||||
s_ex.printStackTrace();
|
||||
System.exit(1);
|
||||
}catch(IOException io_ex){
|
||||
io_ex.printStackTrace();
|
||||
System.exit(1);
|
||||
}catch(NumberFormatException num_ex){
|
||||
usage();
|
||||
num_ex.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
}else{
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
}//End of class
|
|
@ -0,0 +1,160 @@
|
|||
/* Copyright (c) 2009, Nathan Freitas, The Guardian Project - http://openideals.com/guardian */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
package org.torproject.android;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class TorBinaryInstaller implements TorConstants {
|
||||
|
||||
private final static String LOG_TAG = "Tor";
|
||||
|
||||
|
||||
public TorBinaryInstaller ()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the binary installation if the file doesn't exist or is forced
|
||||
*/
|
||||
public void start (boolean force)
|
||||
{
|
||||
boolean binaryExists = new File(TOR_BINARY_INSTALL_PATH).exists();
|
||||
|
||||
Log.i(LOG_TAG,"Tor binary exists=" + binaryExists);
|
||||
|
||||
if (!binaryExists || force)
|
||||
installFromZip ();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the Tor binary from the APK file using ZIP
|
||||
*/
|
||||
private void installFromZip ()
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
ZipFile zip = new ZipFile(APK_PATH);
|
||||
|
||||
ZipEntry zipen = zip.getEntry(TOR_BINARY_ZIP_KEY);
|
||||
streamToFile(zip.getInputStream(zipen),TOR_BINARY_INSTALL_PATH);
|
||||
|
||||
zipen = zip.getEntry(TORRC_ZIP_KEY);
|
||||
streamToFile(zip.getInputStream(zipen),TORRC_INSTALL_PATH);
|
||||
|
||||
zip.close();
|
||||
|
||||
Log.i(LOG_TAG,"SUCCESS: unzipped tor binary from apk");
|
||||
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
Log.i(LOG_TAG,"FAIL: unable to unzip tor binary from apk",ioe);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the inputstream contents to the file
|
||||
*/
|
||||
private static void streamToFile(InputStream stm, String targetFilename)
|
||||
|
||||
{
|
||||
|
||||
FileOutputStream stmOut = null;
|
||||
|
||||
byte[] buffer = new byte[FILE_WRITE_BUFFER_SIZE];
|
||||
|
||||
int bytecount;
|
||||
|
||||
|
||||
File outFile = new File(targetFilename);
|
||||
|
||||
try {
|
||||
outFile.createNewFile();
|
||||
|
||||
stmOut = new FileOutputStream(outFile);
|
||||
}
|
||||
|
||||
catch (java.io.IOException e)
|
||||
|
||||
{
|
||||
|
||||
Log.i(LOG_TAG,"Error opening output file " + targetFilename,e);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
try
|
||||
|
||||
{
|
||||
|
||||
while ((bytecount = stm.read(buffer)) > 0)
|
||||
|
||||
{
|
||||
|
||||
stmOut.write(buffer, 0, bytecount);
|
||||
|
||||
}
|
||||
|
||||
stmOut.close();
|
||||
|
||||
}
|
||||
|
||||
catch (java.io.IOException e)
|
||||
|
||||
{
|
||||
|
||||
Log.i(LOG_TAG,"Error writing output file '" + targetFilename + "': " + e.toString());
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//copy the file from inputstream to File output - alternative impl
|
||||
public void copyFile (InputStream is, File outputFile)
|
||||
{
|
||||
|
||||
try {
|
||||
outputFile.createNewFile();
|
||||
DataOutputStream out = new DataOutputStream(new FileOutputStream(outputFile));
|
||||
DataInputStream in = new DataInputStream(is);
|
||||
|
||||
int b;
|
||||
byte[] data = new byte[1024];
|
||||
|
||||
while ((b = in.read(data)) != -1) {
|
||||
out.write(data);
|
||||
}
|
||||
//
|
||||
out.flush();
|
||||
out.close();
|
||||
in.close();
|
||||
// chmod?
|
||||
|
||||
|
||||
|
||||
} catch (IOException ex) {
|
||||
Log.e(LOG_TAG, "error copying binary", ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/* Copyright (c) 2009, Nathan Freitas, The Guardian Project - http://openideals.com/guardian */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
package org.torproject.android;
|
||||
|
||||
public interface TorConstants {
|
||||
|
||||
//home directory of Android application
|
||||
public final static String TOR_HOME = "/data/data/org.torproject.android/";
|
||||
|
||||
//name of the tor C binary
|
||||
public final static String TOR_BINARY_ASSET_KEY = "tor";
|
||||
|
||||
//path to install the Tor binary too
|
||||
public final static String TOR_BINARY_INSTALL_PATH = TOR_HOME + TOR_BINARY_ASSET_KEY;
|
||||
|
||||
//key of the tor binary in the Zip file
|
||||
public final static String TOR_BINARY_ZIP_KEY = "assets/" + TOR_BINARY_ASSET_KEY;
|
||||
|
||||
//torrc file name
|
||||
public final static String TORRC_ASSET_KEY = "torrc";
|
||||
|
||||
//path to install torrc to within the android app data folder
|
||||
public final static String TORRC_INSTALL_PATH = TOR_HOME + TORRC_ASSET_KEY;
|
||||
|
||||
//key of the torrc file in the Zip file
|
||||
public final static String TORRC_ZIP_KEY = "assets/" + TORRC_ASSET_KEY;
|
||||
|
||||
//where to send the notices log
|
||||
public final static String TOR_LOG_PATH = TOR_HOME + "notices.log";
|
||||
|
||||
//control port cookie path
|
||||
public final static String TOR_CONTROL_AUTH_COOKIE = TOR_HOME + "data/control_auth_cookie";
|
||||
|
||||
//how to launch tor
|
||||
public final static String TOR_COMMAND_LINE_ARGS = "-f " + TORRC_INSTALL_PATH;
|
||||
|
||||
//various console cmds
|
||||
public final static String SHELL_CMD_CHMOD = "/system/bin/chmod";
|
||||
public final static String SHELL_CMD_KILL = "/system/bin/kill";
|
||||
public final static String SHELL_CMD_RM = "/system/bin/rm";
|
||||
public final static String SHELL_CMD_PS = "ps";
|
||||
public final static String CHMOD_EXE_VALUE = "777";
|
||||
|
||||
//path of the installed APK file
|
||||
public final static String APK_PATH = "/data/app/org.torproject.android.apk";
|
||||
|
||||
//path to check Tor against
|
||||
public final static String URL_TOR_CHECK = "http://check.torproject.org";
|
||||
|
||||
public final static int FILE_WRITE_BUFFER_SIZE = 2048;
|
||||
|
||||
//HTTP Proxy server port
|
||||
public final static int PORT_HTTP = 8118; //just like Privoxy!
|
||||
|
||||
//Socks port client connects to, server is the Tor binary
|
||||
public final static int PORT_SOCKS = 9050;
|
||||
|
||||
//what is says!
|
||||
public final static String IP_LOCALHOST = "127.0.0.1";
|
||||
public final static int TOR_CONTROL_PORT = 9051;
|
||||
public final static int UPDATE_TIMEOUT = 3000;
|
||||
|
||||
public final static String DEFAULT_HOME_PAGE = "file:///android_asset/help.html";// "http://check.torproject.org";
|
||||
|
||||
//status to communicate state
|
||||
public final static int STATUS_OFF = 0;
|
||||
public final static int STATUS_ON = 1;
|
||||
public final static int STATUS_STARTING_UP = 2;
|
||||
public final static int STATUS_SHUTTING_DOWN = 3;
|
||||
|
||||
//control port
|
||||
public final static String TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE = "Bootstrapped 100%";
|
||||
|
||||
}
|
|
@ -0,0 +1,587 @@
|
|||
/* Copyright (c) 2009, Nathan Freitas, The Guardian Project - http://openideals.com/guardian */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
package org.torproject.android;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
import net.freehaven.tor.control.EventHandler;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.webkit.JsResult;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class TorControlPanel extends Activity implements OnClickListener, TorConstants, EventHandler
|
||||
{
|
||||
|
||||
private final static String TAG = "Tor";
|
||||
|
||||
private static Intent torService = null;
|
||||
|
||||
private boolean updateLog = false;
|
||||
private boolean updateStatus = false;
|
||||
|
||||
private TextView lblStatus = null;
|
||||
private ImageView imgStatus = null;
|
||||
private String txtStatus = "";
|
||||
private int torStatus = STATUS_OFF;
|
||||
|
||||
private Thread threadStatus = null;
|
||||
|
||||
private WebView mWebView;
|
||||
|
||||
private int currentView = 0;
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setTheme(android.R.style.Theme_Black);
|
||||
|
||||
|
||||
showMain();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
|
||||
MenuItem mItem = menu.add(0, 1, Menu.NONE, "Home");
|
||||
MenuItem mItem2 = menu.add(0, 2, Menu.NONE, "Settings");
|
||||
MenuItem mItem3 = menu.add(0, 3, Menu.NONE, "Log");
|
||||
MenuItem mItem4 = menu.add(0, 4, Menu.NONE, "Help");
|
||||
|
||||
mItem.setIcon(R.drawable.ic_menu_home);
|
||||
mItem2.setIcon(R.drawable.ic_menu_register);
|
||||
mItem3.setIcon(R.drawable.ic_menu_reports);
|
||||
mItem4.setIcon(R.drawable.ic_menu_about);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.app.Activity#onMenuItemSelected(int, android.view.MenuItem)
|
||||
*/
|
||||
@Override
|
||||
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
||||
|
||||
super.onMenuItemSelected(featureId, item);
|
||||
|
||||
if (item.getItemId() == 1)
|
||||
{
|
||||
this.showMain();
|
||||
}
|
||||
else if (item.getItemId() == 2)
|
||||
{
|
||||
this.showSettings();
|
||||
}
|
||||
else if (item.getItemId() == 3)
|
||||
{
|
||||
this.showMessageLog();
|
||||
}
|
||||
else if (item.getItemId() == 4)
|
||||
{
|
||||
this.showWeb(DEFAULT_HOME_PAGE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event){
|
||||
if(keyCode==KeyEvent.KEYCODE_BACK){
|
||||
if(currentView != R.layout.layout_main){
|
||||
|
||||
showMain ();
|
||||
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
}
|
||||
|
||||
return super.onKeyDown(keyCode, event);
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.app.Activity#onPause()
|
||||
*/
|
||||
@Override
|
||||
protected void onPause() {
|
||||
// TODO Auto-generated method stub
|
||||
super.onPause();
|
||||
|
||||
TorService.setStatus(torStatus);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.app.Activity#onResume()
|
||||
*/
|
||||
@Override
|
||||
protected void onResume() {
|
||||
// TODO Auto-generated method stub
|
||||
super.onResume();
|
||||
|
||||
torStatus = TorService.getStatus();
|
||||
|
||||
updateStatus ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.app.Activity#onStart()
|
||||
*/
|
||||
@Override
|
||||
protected void onStart() {
|
||||
// TODO Auto-generated method stub
|
||||
super.onStart();
|
||||
|
||||
torStatus = TorService.getStatus();
|
||||
|
||||
|
||||
updateStatus ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.app.Activity#onStop()
|
||||
*/
|
||||
@Override
|
||||
protected void onStop() {
|
||||
// TODO Auto-generated method stub
|
||||
super.onStop();
|
||||
|
||||
TorService.setStatus(torStatus);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Show the main form UI
|
||||
*/
|
||||
private void showMain ()
|
||||
{
|
||||
updateLog = false;
|
||||
updateStatus = true;
|
||||
|
||||
currentView = R.layout.layout_main;
|
||||
setContentView(currentView);
|
||||
|
||||
findViewById(R.id.imgStatus).setOnClickListener(this);
|
||||
|
||||
lblStatus = (TextView)findViewById(R.id.lblStatus);
|
||||
imgStatus = (ImageView)findViewById(R.id.imgStatus);
|
||||
|
||||
updateStatus();
|
||||
}
|
||||
|
||||
private void showWeb (String url)
|
||||
{
|
||||
|
||||
|
||||
currentView =R.layout.layout_web;
|
||||
setContentView(currentView);
|
||||
|
||||
mWebView = (WebView) findViewById(R.id.webview);
|
||||
|
||||
WebSettings webSettings = mWebView.getSettings();
|
||||
webSettings.setSavePassword(false);
|
||||
webSettings.setSaveFormData(false);
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
|
||||
|
||||
mWebView.setWebChromeClient(new MyWebChromeClient());
|
||||
|
||||
mWebView.loadUrl(url);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Show the message log UI
|
||||
*/
|
||||
private void showMessageLog ()
|
||||
{
|
||||
currentView = R.layout.layout_log;
|
||||
setContentView(currentView);
|
||||
((Button)findViewById(R.id.btnLogClear)).setOnClickListener(this);
|
||||
|
||||
updateStatus = false;
|
||||
updateLog = true;
|
||||
|
||||
Thread thread = new Thread ()
|
||||
{
|
||||
public void run ()
|
||||
{
|
||||
|
||||
while (updateLog)
|
||||
{
|
||||
|
||||
try {
|
||||
Thread.sleep(UPDATE_TIMEOUT);
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
handler.sendEmptyMessage(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
thread.start();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Load the Tor log and display it in a text field
|
||||
*/
|
||||
private void updateMessageLog ()
|
||||
{
|
||||
|
||||
TextView tvLog = (TextView)findViewById(R.id.messageLog);
|
||||
|
||||
if (tvLog != null)
|
||||
{
|
||||
String output = loadTextFile(TOR_LOG_PATH);
|
||||
|
||||
tvLog.setText(output);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle to reload Tor debug log every few seconds while viewing it
|
||||
*/
|
||||
private Handler handler = new Handler() {
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
|
||||
updateMessageLog ();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Handle to reload Tor debug log every few seconds while viewing it
|
||||
*/
|
||||
private Handler handlerStatus = new Handler() {
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
|
||||
updateStatus();
|
||||
|
||||
// Toast.makeText(this,txtStatus, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Load the basic settings application to display torrc
|
||||
* TODO: these needs to be improved into an actual form GUI
|
||||
*/
|
||||
private void showSettings ()
|
||||
{
|
||||
updateStatus = false;
|
||||
updateLog = false;
|
||||
|
||||
currentView = R.layout.layout_settings;
|
||||
setContentView(currentView);
|
||||
|
||||
|
||||
String output = loadTextFile(TORRC_INSTALL_PATH);
|
||||
|
||||
TextView tvSettings = (TextView)findViewById(R.id.textSettings);
|
||||
((Button)findViewById(R.id.btnSettingsSave)).setOnClickListener(this);
|
||||
tvSettings.setText(output);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the state of the running/not running graphic and label
|
||||
*/
|
||||
public void updateStatus ()
|
||||
{
|
||||
|
||||
if (imgStatus != null)
|
||||
{
|
||||
|
||||
if (torStatus == STATUS_ON)
|
||||
{
|
||||
imgStatus.setImageResource(R.drawable.toron);
|
||||
lblStatus.setText("ORbot is running\n- touch the bot to stop -");
|
||||
updateStatus = false;
|
||||
}
|
||||
else if (torStatus == STATUS_STARTING_UP)
|
||||
{
|
||||
imgStatus.setImageResource(R.drawable.torstarting);
|
||||
|
||||
lblStatus.setText("ORbot reports:\n\"" + txtStatus + "\"");
|
||||
|
||||
|
||||
}
|
||||
else if (torStatus == STATUS_SHUTTING_DOWN)
|
||||
{
|
||||
imgStatus.setImageResource(R.drawable.torstopping);
|
||||
lblStatus.setText("ORbot is shutting down\nplease wait...");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
imgStatus.setImageResource(R.drawable.toroff);
|
||||
lblStatus.setText("ORbot is not running\n- touch the bot to start -");
|
||||
updateStatus = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see android.view.View.OnClickListener#onClick(android.view.View)
|
||||
*/
|
||||
public void onClick(View view) {
|
||||
|
||||
// the start button
|
||||
if (view.getId()==R.id.imgStatus)
|
||||
{
|
||||
//if Tor binary is not running, then start the service up
|
||||
if (TorService.getStatus()==STATUS_OFF)
|
||||
{
|
||||
torStatus = STATUS_STARTING_UP;
|
||||
txtStatus = "Connecting to Tor...";
|
||||
updateStatus();
|
||||
|
||||
startTorService ();
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
torStatus = STATUS_SHUTTING_DOWN;
|
||||
updateStatus();
|
||||
|
||||
stopService(torService);
|
||||
|
||||
torStatus = STATUS_OFF;
|
||||
|
||||
updateStatus();
|
||||
}
|
||||
|
||||
}
|
||||
else if (view.getId()==R.id.btnLogClear)
|
||||
{
|
||||
|
||||
saveTextFile(TOR_LOG_PATH,"");
|
||||
}
|
||||
else if (view.getId()==R.id.btnSettingsSave)
|
||||
{
|
||||
|
||||
TextView tvSettings = (TextView)findViewById(R.id.textSettings);
|
||||
String newSettings = tvSettings.getText().toString();
|
||||
saveTextFile(TORRC_INSTALL_PATH, newSettings);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void startTorService ()
|
||||
{
|
||||
if (torService == null)
|
||||
{
|
||||
torService = new Intent(this, TorService.class);
|
||||
//torService.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
TorService.setActivity(this);
|
||||
}
|
||||
|
||||
startService(torService);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Load the log file text
|
||||
*/
|
||||
public static String loadTextFile (String path)
|
||||
{
|
||||
String line = null;
|
||||
|
||||
StringBuffer out = new StringBuffer();
|
||||
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader((new FileReader(new File(path))));
|
||||
|
||||
while ((line = reader.readLine()) != null)
|
||||
{
|
||||
out.append(line);
|
||||
out.append('\n');
|
||||
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return out.toString();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Load the log file text
|
||||
*/
|
||||
public static boolean saveTextFile (String path, String contents)
|
||||
{
|
||||
|
||||
try {
|
||||
|
||||
FileWriter writer = new FileWriter( path, false );
|
||||
writer.write( contents );
|
||||
|
||||
writer.close();
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
} catch (IOException e) {
|
||||
// Log.i(TAG, "error writing file: " + path, e);
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void bandwidthUsed(long read, long written) {
|
||||
Log.i(TAG,"BW Used: read=" + read + " written=" + written);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void circuitStatus(String status, String circID, String path) {
|
||||
Log.i(TAG,"CircuitStatus=" + status + ": " + circID);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void message(String severity, String msg) {
|
||||
|
||||
// Log.println(priority, tag, msg)("["+severity+"] "+msg);
|
||||
//Toast.makeText(, text, duration)
|
||||
// Toast.makeText(ACTIVITY, severity + ": " + msg, Toast.LENGTH_SHORT);
|
||||
Log.i(TAG, "[Tor Control Port] " + severity + ": " + msg);
|
||||
|
||||
if (msg.indexOf(TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE)!=-1)
|
||||
{
|
||||
torStatus = STATUS_ON;
|
||||
|
||||
|
||||
|
||||
//setupWebProxy(true);
|
||||
|
||||
}
|
||||
|
||||
|
||||
txtStatus = msg;
|
||||
handlerStatus.sendEmptyMessage(0);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void newDescriptors(List<String> orList) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void orConnStatus(String status, String orName) {
|
||||
|
||||
Log.i(TAG,"OrConnStatus=" + status + ": " + orName);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void streamStatus(String status, String streamID, String target) {
|
||||
Log.i(TAG,"StreamStatus=" + status + ": " + streamID);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void unrecognized(String type, String msg) {
|
||||
Log.i(TAG,"unrecognized log=" + type + ": " + msg);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provides a hook for calling "alert" from javascript. Useful for
|
||||
* debugging your javascript.
|
||||
*/
|
||||
final class MyWebChromeClient extends WebChromeClient {
|
||||
@Override
|
||||
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
|
||||
Log.d(TAG, message);
|
||||
result.confirm();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,617 @@
|
|||
/* Copyright (c) 2009, Nathan Freitas, The Guardian Project - http://openideals.com/guardian */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
package org.torproject.android;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.ConnectException;
|
||||
import java.net.Socket;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import net.freehaven.tor.control.EventHandler;
|
||||
import net.freehaven.tor.control.NullEventHandler;
|
||||
import net.freehaven.tor.control.TorControlConnection;
|
||||
import net.sourceforge.jsocks.socks.Proxy;
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class TorService extends Service implements TorConstants
|
||||
{
|
||||
|
||||
private static TorControlPanel ACTIVITY = null;
|
||||
|
||||
private final static String TAG = "TorService";
|
||||
|
||||
private static HttpProxy webProxy = null;
|
||||
|
||||
private static int currentStatus = STATUS_OFF;
|
||||
|
||||
private TorControlConnection conn = null;
|
||||
|
||||
private Timer timer = new Timer ();
|
||||
private final static int UPDATE_INTERVAL = 60000;
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
Log.i(TAG,"TorService: onCreate");
|
||||
|
||||
timer.scheduleAtFixedRate(
|
||||
new TimerTask() {
|
||||
public void run() {
|
||||
|
||||
//do nothing
|
||||
// Log.i(TAG,"TorService: task is running");
|
||||
}
|
||||
},
|
||||
0,
|
||||
UPDATE_INTERVAL);
|
||||
|
||||
|
||||
int procId = findProcessId(TorConstants.TOR_BINARY_INSTALL_PATH);
|
||||
|
||||
if (procId != -1)
|
||||
{
|
||||
Log.i(TAG,"Found existing Tor process");
|
||||
|
||||
try {
|
||||
currentStatus = STATUS_STARTING_UP;
|
||||
|
||||
initControlConnection();
|
||||
|
||||
getTorStatus();
|
||||
|
||||
if (webProxy != null)
|
||||
{
|
||||
if (webProxy.isRunning())
|
||||
{
|
||||
//do nothing
|
||||
Log.i(TAG, "Web Proxy is already running");
|
||||
}
|
||||
else
|
||||
{
|
||||
//do nothing
|
||||
Log.i(TAG, "killing Web Proxy");
|
||||
webProxy.closeSocket();
|
||||
setupWebProxy(true);
|
||||
}
|
||||
}
|
||||
else //do something
|
||||
{
|
||||
setupWebProxy(true);
|
||||
}
|
||||
|
||||
currentStatus = STATUS_ON;
|
||||
|
||||
} catch (RuntimeException e) {
|
||||
Log.i(TAG,"Unable to connect to existing Tor instance,",e);
|
||||
currentStatus = STATUS_OFF;
|
||||
this.stopTor();
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.i(TAG,"Unable to connect to existing Tor instance,",e);
|
||||
currentStatus = STATUS_OFF;
|
||||
this.stopTor();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.app.Service#onLowMemory()
|
||||
*/
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
// TODO Auto-generated method stub
|
||||
super.onLowMemory();
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.app.Service#onUnbind(android.content.Intent)
|
||||
*/
|
||||
@Override
|
||||
public boolean onUnbind(Intent intent) {
|
||||
// TODO Auto-generated method stub
|
||||
return super.onUnbind(intent);
|
||||
}
|
||||
|
||||
|
||||
public static int getStatus ()
|
||||
{
|
||||
|
||||
return currentStatus;
|
||||
|
||||
}
|
||||
|
||||
public static void setStatus (int newStatus)
|
||||
{
|
||||
currentStatus = newStatus;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.app.Service#onRebind(android.content.Intent)
|
||||
*/
|
||||
@Override
|
||||
public void onRebind(Intent intent) {
|
||||
// TODO Auto-generated method stub
|
||||
super.onRebind(intent);
|
||||
|
||||
Log.i(TAG,"on rebind");
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.app.Service#onStart(android.content.Intent, int)
|
||||
*/
|
||||
@Override
|
||||
public void onStart(Intent intent, int startId) {
|
||||
// TODO Auto-generated method stub
|
||||
super.onStart(intent, startId);
|
||||
|
||||
Log.i(TAG,"onStart called");
|
||||
|
||||
initTor();
|
||||
|
||||
setupWebProxy (true);
|
||||
}
|
||||
|
||||
|
||||
public void onDestroy ()
|
||||
{
|
||||
super.onDestroy();
|
||||
|
||||
Log.i(TAG,"onDestroy called");
|
||||
|
||||
if (timer != null) timer.cancel();
|
||||
|
||||
stopTor();
|
||||
}
|
||||
|
||||
private void stopTor ()
|
||||
{
|
||||
currentStatus = STATUS_SHUTTING_DOWN;
|
||||
|
||||
setupWebProxy(false);
|
||||
|
||||
killTorProcess ();
|
||||
|
||||
currentStatus = STATUS_OFF;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void setActivity(TorControlPanel activity) {
|
||||
ACTIVITY = activity;
|
||||
}
|
||||
|
||||
private void setupWebProxy (boolean enabled)
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
|
||||
if (webProxy != null)
|
||||
{
|
||||
webProxy.closeSocket();
|
||||
webProxy = null;
|
||||
|
||||
}
|
||||
|
||||
Log.i(TAG,"Starting up Web Proxy on port: " + PORT_HTTP);
|
||||
//httpd s
|
||||
webProxy = new HttpProxy(PORT_HTTP);
|
||||
webProxy.setDoSocks(true);
|
||||
webProxy.start();
|
||||
|
||||
//socks
|
||||
try
|
||||
{
|
||||
|
||||
Proxy.setDefaultProxy(IP_LOCALHOST,PORT_SOCKS);
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.w(TAG,e.getMessage());
|
||||
}
|
||||
|
||||
Log.i(TAG,"Web Proxy enabled...");
|
||||
|
||||
|
||||
//Settings.System.putString(getContentResolver(), Settings.System.HTTP_PROXY, proxySetting);//enable proxy
|
||||
// Settings.Secure.putString(getContentResolver(), Settings.Secure.HTTP_PROXY, proxySetting);//enable proxy
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//Log.i(TAG,"Turning off Socks/Tor routing on Web Proxy");
|
||||
|
||||
if (webProxy != null)
|
||||
{
|
||||
//logNotice("Tor is disabled - browsing is not anonymous!");
|
||||
//webProxy.setDoSocks(false);
|
||||
|
||||
webProxy.closeSocket();
|
||||
webProxy = null;
|
||||
Log.i(TAG,"WebProxy ServerSocket closed");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void reloadConfig ()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (conn == null)
|
||||
{
|
||||
initControlConnection ();
|
||||
}
|
||||
|
||||
if (conn != null)
|
||||
{
|
||||
conn.signal("RELOAD");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.i(TAG,"Unable to reload configuration",e);
|
||||
}
|
||||
}
|
||||
|
||||
private void killTorProcess ()
|
||||
{
|
||||
|
||||
if (conn != null)
|
||||
{
|
||||
try {
|
||||
Log.i(TAG,"sending SHUTDOWN signal");
|
||||
conn.signal("SHUTDOWN");
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
Log.i(TAG,"error shutting down Tor via connection",e);
|
||||
}
|
||||
conn = null;
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
|
||||
}
|
||||
|
||||
int procId = findProcessId(TorConstants.TOR_BINARY_INSTALL_PATH);
|
||||
|
||||
while (procId != -1)
|
||||
{
|
||||
|
||||
Log.i(TAG,"Found Tor PID=" + procId + " - killing now...");
|
||||
|
||||
doCommand(SHELL_CMD_KILL, procId + "");
|
||||
|
||||
procId = findProcessId(TorConstants.TOR_BINARY_INSTALL_PATH);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static void logNotice (String msg)
|
||||
{
|
||||
|
||||
Log.i(TAG, msg);
|
||||
|
||||
}
|
||||
|
||||
private void checkBinary ()
|
||||
{
|
||||
|
||||
boolean binaryExists = new File(TOR_BINARY_INSTALL_PATH).exists();
|
||||
|
||||
if (!binaryExists)
|
||||
{
|
||||
killTorProcess ();
|
||||
|
||||
TorBinaryInstaller installer = new TorBinaryInstaller();
|
||||
installer.start(true);
|
||||
|
||||
binaryExists = new File(TOR_BINARY_INSTALL_PATH).exists();
|
||||
if (binaryExists)
|
||||
{
|
||||
logNotice("Tor binary installed!");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
logNotice("Tor binary install FAILED!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Log.i(TAG,"Setting permission on Tor binary");
|
||||
doCommand(SHELL_CMD_CHMOD, CHMOD_EXE_VALUE + ' ' + TOR_BINARY_INSTALL_PATH);
|
||||
}
|
||||
|
||||
public void initTor ()
|
||||
{
|
||||
try {
|
||||
|
||||
currentStatus = STATUS_STARTING_UP;
|
||||
|
||||
killTorProcess ();
|
||||
|
||||
checkBinary ();
|
||||
|
||||
doCommand(SHELL_CMD_RM,TOR_LOG_PATH);
|
||||
|
||||
Log.i(TAG,"Starting tor process");
|
||||
doCommand(TOR_BINARY_INSTALL_PATH, TOR_COMMAND_LINE_ARGS);
|
||||
|
||||
int procId = findProcessId(TorConstants.TOR_BINARY_INSTALL_PATH);
|
||||
|
||||
if (procId == -1)
|
||||
{
|
||||
doCommand(TOR_BINARY_INSTALL_PATH, TOR_COMMAND_LINE_ARGS);
|
||||
procId = findProcessId(TorConstants.TOR_BINARY_INSTALL_PATH);
|
||||
}
|
||||
|
||||
Log.i(TAG,"Tor process id=" + procId);
|
||||
|
||||
currentStatus = STATUS_STARTING_UP;
|
||||
logNotice("Tor is starting up...");
|
||||
|
||||
Thread.sleep(500);
|
||||
initControlConnection ();
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
Log.w(TAG,"unable to start Tor Process",e);
|
||||
|
||||
e.printStackTrace();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void logStream (InputStream is)
|
||||
{
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
String line = null;
|
||||
|
||||
|
||||
try {
|
||||
while ((line = reader.readLine()) != null)
|
||||
{
|
||||
Log.i(TAG, line);
|
||||
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent arg0) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int findProcessId(String command)
|
||||
{
|
||||
int procId = -1;
|
||||
|
||||
Runtime r = Runtime.getRuntime();
|
||||
|
||||
Process procPs = null;
|
||||
|
||||
try {
|
||||
|
||||
procPs = r.exec(SHELL_CMD_PS);
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(procPs.getInputStream()));
|
||||
String line = null;
|
||||
|
||||
while ((line = reader.readLine())!=null)
|
||||
{
|
||||
if (line.indexOf(command)!=-1)
|
||||
{
|
||||
|
||||
StringTokenizer st = new StringTokenizer(line," ");
|
||||
st.nextToken(); //proc owner
|
||||
|
||||
procId = Integer.parseInt(st.nextToken().trim());
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "error: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
return procId;
|
||||
|
||||
}
|
||||
|
||||
public static Process doCommand(String command, String arg1)
|
||||
{
|
||||
|
||||
Runtime r = Runtime.getRuntime();
|
||||
|
||||
Process child = null;
|
||||
|
||||
try {
|
||||
if(child != null) {
|
||||
child.destroy();
|
||||
child = null;
|
||||
}
|
||||
|
||||
child = r.exec(command + ' ' + arg1);
|
||||
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "error: " + e.getMessage());
|
||||
}
|
||||
|
||||
return child;
|
||||
|
||||
}
|
||||
|
||||
public static String generateHashPassword ()
|
||||
{
|
||||
/*
|
||||
PasswordDigest d = PasswordDigest.generateDigest();
|
||||
byte[] s = d.getSecret(); // pass this to authenticate
|
||||
String h = d.getHashedPassword(); // pass this to the Tor on startup.
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
|
||||
public void initControlConnection () throws Exception, RuntimeException
|
||||
{
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
Log.i(TAG,"Connecting to control port: " + TOR_CONTROL_PORT);
|
||||
Socket s = new Socket(IP_LOCALHOST, TOR_CONTROL_PORT);
|
||||
conn = TorControlConnection.getConnection(s);
|
||||
// conn.authenticate(new byte[0]); // See section 3.2
|
||||
|
||||
Log.i(TAG,"SUCCESS connected to control port");
|
||||
|
||||
//
|
||||
File fileCookie = new File(TOR_CONTROL_AUTH_COOKIE);
|
||||
byte[] cookie = new byte[(int)fileCookie.length()];
|
||||
new FileInputStream(new File(TOR_CONTROL_AUTH_COOKIE)).read(cookie);
|
||||
conn.authenticate(cookie);
|
||||
|
||||
Log.i(TAG,"SUCCESS authenticated to control port");
|
||||
|
||||
addEventHandler();
|
||||
|
||||
break; //don't need to retry
|
||||
}
|
||||
catch (ConnectException ce)
|
||||
{
|
||||
Log.i(TAG,"Attempt " + i + ": Error connecting to control port; retrying...");
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void modifyConf () throws IOException
|
||||
{
|
||||
// Get one configuration variable.
|
||||
List options = conn.getConf("contact");
|
||||
// Get a set of configuration variables.
|
||||
// List options = conn.getConf(Arrays.asList(new String[]{
|
||||
// "contact", "orport", "socksport"}));
|
||||
// Change a single configuration variable
|
||||
conn.setConf("BandwidthRate", "1 MB");
|
||||
// Change several configuration variables
|
||||
conn.setConf(Arrays.asList(new String[]{
|
||||
"HiddenServiceDir /home/tor/service1",
|
||||
"HiddenServicePort 80",
|
||||
}));
|
||||
// Reset some variables to their defaults
|
||||
conn.resetConf(Arrays.asList(new String[]{
|
||||
"contact", "socksport"
|
||||
}));
|
||||
// Flush the configuration to disk.
|
||||
conn.saveConf();
|
||||
|
||||
}
|
||||
|
||||
private void getTorStatus () throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
if (conn != null)
|
||||
{
|
||||
// get a single value.
|
||||
|
||||
// get several values
|
||||
|
||||
if (currentStatus == STATUS_STARTING_UP)
|
||||
{
|
||||
//Map vals = conn.getInfo(Arrays.asList(new String[]{
|
||||
// "status/bootstrap-phase", "status","version"}));
|
||||
|
||||
String bsPhase = conn.getInfo("status/bootstrap-phase");
|
||||
// Log.i(TAG, "bootstrap-phase: " + bsPhase);
|
||||
|
||||
if (bsPhase.indexOf("PROGRESS=100")!=-1)
|
||||
{
|
||||
currentStatus = STATUS_ON;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// String status = conn.getInfo("status/circuit-established");
|
||||
// Log.i(TAG, "status/circuit-established=" + status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
currentStatus = STATUS_OFF;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.i(TAG, "Unable to get Tor status from control port");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void addEventHandler () throws IOException
|
||||
{
|
||||
// We extend NullEventHandler so that we don't need to provide empty
|
||||
// implementations for all the events we don't care about.
|
||||
// ...
|
||||
Log.i(TAG,"adding control port event handler");
|
||||
|
||||
conn.setEventHandler(ACTIVITY);
|
||||
|
||||
conn.setEvents(Arrays.asList(new String[]{
|
||||
"ORCONN", "CIRC", "NOTICE", "ERR"}));
|
||||
// conn.setEvents(Arrays.asList(new String[]{
|
||||
// "DEBUG", "INFO", "NOTICE", "WARN", "ERR"}));
|
||||
|
||||
Log.i(TAG,"SUCCESS added control port event handler");
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue