0.0.2a update; improved Service mgmt; Control Port callbacks; better UI graphics; Help page

svn:r21065
This commit is contained in:
Nathan Freitas 2009-11-30 16:39:13 +00:00
parent a97974c9ba
commit 13ba7d3cff
18 changed files with 534 additions and 278 deletions

View File

@ -8,7 +8,7 @@
<uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" />
<application android:icon="@drawable/icon" android:label="@string/app_name" <application android:icon="@drawable/icon" android:label="@string/app_name"
android:debuggable="true"> android:debuggable="false">
<activity android:name=".TorControlPanel" <activity android:name=".TorControlPanel"
android:label="@string/app_name"> android:label="@string/app_name">
<intent-filter> <intent-filter>
@ -16,7 +16,10 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<service android:name=".TorService" android:enabled="true" android:exported="true"/>
<service android:name=".TorService" android:enabled="true" android:exported="true"/>
</application> </application>

View File

@ -1,3 +1,9 @@
0.0.2a - 2009-11-30
- Update user interace layout and graphics
- Modified service launch, shutdown and handling
- Improved event handler on Tor Control port callbacks
- Added Help page
0.0.2 - 2009-11-27 0.0.2 - 2009-11-27
- Major improvement to the user interface including relative layout for different screens - Major improvement to the user interface including relative layout for different screens
- New graphics resources - New graphics resources

48
Orbot/assets/help.html Normal file
View File

@ -0,0 +1,48 @@
<html>
<head>
<title>help.html</title>
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
<style>
body
{
background:black;
color:white;
font-family:arial;
}
a, a:link, a:visited
{
color:#00ff00;
}
</style>
</head>
<body>
<h2>ORbot</h2>
<i>Onion Routing Robot - v0.0.2a / November 30, 2009</i><br/>
<hr/>
<h3>How to use ORbot</h3>
Simply touch the Orbot icon on the main screen and wait for it to fully connect to the Tor network. You can use the Menu -> Log option to view
more detailed information about the attempt to connect to the network.
<h3>How to surf anonymously</h3>
Once you have Orbot running and connected to the Tor network, you can utilize the anonymous proxy service in multiple ways:
<ul>
<li>Set your Android APN Proxy (Settings -> Wireless Networks -> Mobile networks -> Access Point Names) to 127.0.0.1/8118</li>
<li>Tell your application to use Web Proxy: 127.0.0.1:8118</li>
<li>Download and use the 'Shadow' browser from the Android Market</li>
</ul>
You can always visit <a href="http://check.torproject.org">http://check.torproject.org</a> to ensure that you are properly connected to the Tor network.
<h3>Bridges and Other Settings</h3>
You can modify the TORRC settings file using the Menu -> Settings option. This is where you can copy and paste in Tor Bridge node addresses
if they are needed in your local area.
<h3>Even More Information!</h3>
If you'd like to learn more about the Tor Project, please visit <a href="http://torproject.org">http://torproject.org</a>.
</body>
</html>

View File

@ -17,7 +17,7 @@
## relay, and not make any local application connections yourself. ## relay, and not make any local application connections yourself.
SocksPort 9050 # what port to open for local application connections SocksPort 9050 # what port to open for local application connections
SocksListenAddress 127.0.0.1 # accept connections only from localhost SocksListenAddress 127.0.0.1 # accept connections only from localhost
#SocksListenAddress 192.168.0.1:9100 # listen on this IP:port also SocksListenAddress 127.0.0.1:1080 # listen on this IP:port also
## Entry policies to allow/deny SOCKS requests based on IP address. ## Entry policies to allow/deny SOCKS requests based on IP address.
## First entry that matches wins. If no SocksPolicy is set, we accept ## First entry that matches wins. If no SocksPolicy is set, we accept

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -12,6 +12,7 @@
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_weight="1.0" android:layout_weight="1.0"
android:textSize="11px"
/> />
</ScrollView> </ScrollView>

View File

@ -32,7 +32,10 @@ android:src="@drawable/toroff"/>
android:text=" \n " android:text=" \n "
android:paddingTop="15px" android:paddingTop="15px"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
android:textStyle="bold" android:textStyle="bold"
android:width="240px"
android:height="100px"
android:textColor="#ffffff" /> android:textColor="#ffffff" />
</TableRow> </TableRow>
</TableLayout> </TableLayout>

View File

@ -13,6 +13,7 @@
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_weight="1.0" android:layout_weight="1.0"
android:singleLine="false" android:singleLine="false"
android:textSize="11px"
/> />
</ScrollView> </ScrollView>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 2008, Google Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<WebView
android:id="@+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
/>
</LinearLayout>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Orbot</string> <string name="app_name">ORbot</string>
<string name="app_version">0.0.1</string> <string name="app_version">0.0.2a</string>
</resources> </resources>

View File

@ -75,9 +75,9 @@ public class HttpProxy extends Thread
private String fwdServer = ""; private String fwdServer = "";
private int fwdPort = 0; private int fwdPort = 0;
private int ptTimeout = ProxyThread.DEFAULT_TIMEOUT; private int ptTimeout = ProxyThread.DEFAULT_TIMEOUT;
private int debugLevel = 0; private int debugLevel = 1;
private PrintStream debugOut = System.out; private PrintStream debugOut = System.out;
private boolean keepRunning = true;
private boolean doSocks = false; private boolean doSocks = false;
private Socks5Proxy sProxy = null; private Socks5Proxy sProxy = null;
@ -220,6 +220,7 @@ public class HttpProxy extends Thread
public void closeSocket () public void closeSocket ()
{ {
try { try {
keepRunning = false;
// close the open server socket // close the open server socket
server.close(); server.close();
// send it a message to make it stop waiting immediately // send it a message to make it stop waiting immediately
@ -245,7 +246,7 @@ public class HttpProxy extends Thread
// client connections // client connections
server = new ServerSocket(thisPort); server = new ServerSocket(thisPort);
while (true) while (keepRunning)
{ {
Socket client = server.accept(); Socket client = server.accept();
ProxyThread t = new ProxyThread(client, doSocks, sProxy); ProxyThread t = new ProxyThread(client, doSocks, sProxy);

View File

@ -37,7 +37,7 @@ public interface TorConstants {
//various console cmds //various console cmds
public final static String SHELL_CMD_CHMOD = "/system/bin/chmod"; public final static String SHELL_CMD_CHMOD = "/system/bin/chmod";
public final static String SHELL_CMD_KILLALL = "/system/bin/kill"; 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_RM = "/system/bin/rm";
public final static String SHELL_CMD_PS = "ps"; public final static String SHELL_CMD_PS = "ps";
public final static String CHMOD_EXE_VALUE = "777"; public final static String CHMOD_EXE_VALUE = "777";
@ -61,6 +61,8 @@ public interface TorConstants {
public final static int TOR_CONTROL_PORT = 9051; public final static int TOR_CONTROL_PORT = 9051;
public final static int UPDATE_TIMEOUT = 3000; 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 //status to communicate state
public final static int STATUS_OFF = 0; public final static int STATUS_OFF = 0;
public final static int STATUS_ON = 1; public final static int STATUS_ON = 1;

View File

@ -8,6 +8,10 @@ import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import net.freehaven.tor.control.EventHandler;
import android.app.Activity; import android.app.Activity;
@ -15,25 +19,42 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; 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.Button;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
public class TorControlPanel extends Activity implements OnClickListener, TorConstants public class TorControlPanel extends Activity implements OnClickListener, TorConstants, EventHandler
{ {
private final static String LOG_TAG = "Tor"; private final static String TAG = "Tor";
private Intent torService = null; private static Intent torService = null;
private boolean updateLog = false; private boolean updateLog = false;
private boolean updateStatus = 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. */ /** Called when the activity is first created. */
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@ -44,7 +65,7 @@ public class TorControlPanel extends Activity implements OnClickListener, TorCon
showMain(); showMain();
} }
@ -54,12 +75,12 @@ public class TorControlPanel extends Activity implements OnClickListener, TorCon
MenuItem mItem = menu.add(0, 1, Menu.NONE, "Home"); MenuItem mItem = menu.add(0, 1, Menu.NONE, "Home");
MenuItem mItem2 = menu.add(0, 2, Menu.NONE, "Settings"); MenuItem mItem2 = menu.add(0, 2, Menu.NONE, "Settings");
MenuItem mItem3 = menu.add(0, 3, Menu.NONE, "Log"); MenuItem mItem3 = menu.add(0, 3, Menu.NONE, "Log");
MenuItem mItem4 = menu.add(0, 4, Menu.NONE, "Browser"); MenuItem mItem4 = menu.add(0, 4, Menu.NONE, "Help");
mItem.setIcon(R.drawable.ic_menu_home); mItem.setIcon(R.drawable.ic_menu_home);
mItem2.setIcon(R.drawable.ic_menu_register); mItem2.setIcon(R.drawable.ic_menu_register);
mItem3.setIcon(R.drawable.ic_menu_reports); mItem3.setIcon(R.drawable.ic_menu_reports);
mItem4.setIcon(R.drawable.ic_menu_goto); mItem4.setIcon(R.drawable.ic_menu_about);
return true; return true;
} }
@ -86,12 +107,28 @@ public class TorControlPanel extends Activity implements OnClickListener, TorCon
} }
else if (item.getItemId() == 4) else if (item.getItemId() == 4)
{ {
Toast.makeText(this, "Not yet implemented!", Toast.LENGTH_SHORT); this.showWeb(DEFAULT_HOME_PAGE);
} }
return true; 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) /* (non-Javadoc)
* @see android.app.Activity#onPause() * @see android.app.Activity#onPause()
@ -100,6 +137,8 @@ public class TorControlPanel extends Activity implements OnClickListener, TorCon
protected void onPause() { protected void onPause() {
// TODO Auto-generated method stub // TODO Auto-generated method stub
super.onPause(); super.onPause();
TorService.setStatus(torStatus);
} }
@ -113,7 +152,9 @@ public class TorControlPanel extends Activity implements OnClickListener, TorCon
// TODO Auto-generated method stub // TODO Auto-generated method stub
super.onResume(); super.onResume();
checkStatus (); torStatus = TorService.getStatus();
updateStatus ();
} }
@ -127,7 +168,10 @@ public class TorControlPanel extends Activity implements OnClickListener, TorCon
// TODO Auto-generated method stub // TODO Auto-generated method stub
super.onStart(); super.onStart();
checkStatus (); torStatus = TorService.getStatus();
updateStatus ();
} }
@ -140,6 +184,8 @@ public class TorControlPanel extends Activity implements OnClickListener, TorCon
protected void onStop() { protected void onStop() {
// TODO Auto-generated method stub // TODO Auto-generated method stub
super.onStop(); super.onStop();
TorService.setStatus(torStatus);
} }
@ -152,38 +198,47 @@ public class TorControlPanel extends Activity implements OnClickListener, TorCon
updateLog = false; updateLog = false;
updateStatus = true; updateStatus = true;
setContentView(R.layout.layout_main); currentView = R.layout.layout_main;
setContentView(currentView);
findViewById(R.id.imgStatus).setOnClickListener(this); findViewById(R.id.imgStatus).setOnClickListener(this);
lblStatus = (TextView)findViewById(R.id.lblStatus);
Thread thread = new Thread () imgStatus = (ImageView)findViewById(R.id.imgStatus);
{
public void run () updateStatus();
{
while (updateStatus)
{
handlerStatus.sendEmptyMessage(0);
try {
Thread.sleep(UPDATE_TIMEOUT);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
thread.start();
} }
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 * Show the message log UI
*/ */
private void showMessageLog () private void showMessageLog ()
{ {
setContentView(R.layout.layout_log); currentView = R.layout.layout_log;
setContentView(currentView);
((Button)findViewById(R.id.btnLogClear)).setOnClickListener(this); ((Button)findViewById(R.id.btnLogClear)).setOnClickListener(this);
updateStatus = false; updateStatus = false;
@ -252,8 +307,9 @@ public class TorControlPanel extends Activity implements OnClickListener, TorCon
@Override @Override
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
checkStatus(); updateStatus();
// Toast.makeText(this,txtStatus, Toast.LENGTH_SHORT).show();
} }
}; };
@ -268,7 +324,8 @@ public class TorControlPanel extends Activity implements OnClickListener, TorCon
updateStatus = false; updateStatus = false;
updateLog = false; updateLog = false;
setContentView(R.layout.layout_settings); currentView = R.layout.layout_settings;
setContentView(currentView);
String output = loadTextFile(TORRC_INSTALL_PATH); String output = loadTextFile(TORRC_INSTALL_PATH);
@ -283,40 +340,36 @@ public class TorControlPanel extends Activity implements OnClickListener, TorCon
/* /*
* Set the state of the running/not running graphic and label * Set the state of the running/not running graphic and label
*/ */
public void checkStatus () public void updateStatus ()
{ {
TextView lblStatus = (TextView)findViewById(R.id.lblStatus);
ImageView imgStatus = (ImageView)findViewById(R.id.imgStatus);
if (imgStatus != null) if (imgStatus != null)
{ {
int torStatus = TorService.getStatus();
if (torStatus == STATUS_ON) if (torStatus == STATUS_ON)
{ {
imgStatus.setImageResource(R.drawable.toron); imgStatus.setImageResource(R.drawable.toron);
lblStatus.setText("Tor is running\n- touch to stop -"); lblStatus.setText("ORbot is running\n- touch the bot to stop -");
updateStatus = false; updateStatus = false;
} }
else if (torStatus == STATUS_STARTING_UP) else if (torStatus == STATUS_STARTING_UP)
{ {
imgStatus.setImageResource(R.drawable.torstarting); imgStatus.setImageResource(R.drawable.torstarting);
lblStatus.setText("Tor is starting up\n(this might take a little bit)");
lblStatus.setText("ORbot reports:\n\"" + txtStatus + "\"");
} }
else if (torStatus == STATUS_SHUTTING_DOWN) else if (torStatus == STATUS_SHUTTING_DOWN)
{ {
imgStatus.setImageResource(R.drawable.torstopping); imgStatus.setImageResource(R.drawable.torstopping);
lblStatus.setText("Tor is shutting down\nplease wait..."); lblStatus.setText("ORbot is shutting down\nplease wait...");
} }
else else
{ {
imgStatus.setImageResource(R.drawable.toroff); imgStatus.setImageResource(R.drawable.toroff);
lblStatus.setText("Tor is not running\n- touch to start -"); lblStatus.setText("ORbot is not running\n- touch the bot to start -");
updateStatus = false; updateStatus = false;
} }
} }
@ -337,26 +390,27 @@ public class TorControlPanel extends Activity implements OnClickListener, TorCon
//if Tor binary is not running, then start the service up //if Tor binary is not running, then start the service up
if (TorService.getStatus()==STATUS_OFF) if (TorService.getStatus()==STATUS_OFF)
{ {
torService = new Intent(this, TorService.class); torStatus = STATUS_STARTING_UP;
torService.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); txtStatus = "Connecting to Tor...";
TorService.setActivity(this); updateStatus();
startService(torService); startTorService ();
} }
else if (TorService.getStatus()==STATUS_ON) else
{ {
torStatus = STATUS_SHUTTING_DOWN;
updateStatus();
//stopService(torService); stopService(torService);
TorService.stopTor (); torStatus = STATUS_OFF;
updateStatus();
} }
showMain ();
} }
else if (view.getId()==R.id.btnLogClear) else if (view.getId()==R.id.btnLogClear)
{ {
@ -375,6 +429,20 @@ public class TorControlPanel extends Activity implements OnClickListener, TorCon
} }
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 * Load the log file text
@ -431,33 +499,89 @@ public class TorControlPanel extends Activity implements OnClickListener, TorCon
} }
/*
* Get the last line of the log file for status display
*/
public static String getLastLine (String path)
{
String line = null;
String lastLine = null;
try {
BufferedReader reader = new BufferedReader((new FileReader(new File(path))));
while ((line = reader.readLine()) != null) @Override
{ public void bandwidthUsed(long read, long written) {
lastLine = line; Log.i(TAG,"BW Used: read=" + read + " written=" + written);
}
} catch (IOException e) { }
// TODO Auto-generated catch block
e.printStackTrace();
} @Override
public void circuitStatus(String status, String circID, String path) {
return lastLine; 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;
}
}
} }

View File

@ -10,11 +10,14 @@ import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.ConnectException;
import java.net.Socket; import java.net.Socket;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.Timer;
import java.util.TimerTask;
import net.freehaven.tor.control.EventHandler; import net.freehaven.tor.control.EventHandler;
import net.freehaven.tor.control.NullEventHandler; import net.freehaven.tor.control.NullEventHandler;
@ -31,35 +34,118 @@ public class TorService extends Service implements TorConstants
private static TorControlPanel ACTIVITY = null; private static TorControlPanel ACTIVITY = null;
private final static String TAG = "Tor"; private final static String TAG = "TorService";
private static HttpProxy webProxy = null; private static HttpProxy webProxy = null;
private static Process procTor = null;
private static int currentStatus = STATUS_OFF; private static int currentStatus = STATUS_OFF;
private static TorControlConnection conn = null; private TorControlConnection conn = null;
private Timer timer = new Timer ();
private final static int UPDATE_INTERVAL = 60000;
/** Called when the activity is first created. */ /** Called when the activity is first created. */
@Override @Override
public void onCreate() { public void onCreate() {
super.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();
}
}
} }
public static int getStatus () /* (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 ()
{ {
try {
getTorStatus();
} catch (IOException e) {
Log.i(TAG,"Unable to get tor status",e);
}
return currentStatus; return currentStatus;
} }
public static void setStatus (int newStatus)
{
currentStatus = newStatus;
}
/* (non-Javadoc) /* (non-Javadoc)
@ -82,54 +168,35 @@ public class TorService extends Service implements TorConstants
// TODO Auto-generated method stub // TODO Auto-generated method stub
super.onStart(intent, startId); super.onStart(intent, startId);
Log.i(TAG,"on start"); Log.i(TAG,"onStart called");
startService(); initTor();
setupWebProxy (true);
} }
private void startService ()
{
Thread thread = new Thread ()
{
public void run ()
{
Log.i(TAG,"Tor thread started");
initTor();
}
};
thread.start();
}
public void onDestroy () public void onDestroy ()
{ {
super.onDestroy();
Log.i(TAG,"onDestroy called");
if (timer != null) timer.cancel();
stopTor();
} }
public static void stopTor () private void stopTor ()
{ {
currentStatus = STATUS_SHUTTING_DOWN; currentStatus = STATUS_SHUTTING_DOWN;
Thread thread = new Thread () setupWebProxy(false);
{
public void run () killTorProcess ();
{
killTorProcess ();
setupWebProxy(false); currentStatus = STATUS_OFF;
currentStatus = STATUS_OFF;
}
};
thread.start();
} }
@ -137,55 +204,62 @@ public class TorService extends Service implements TorConstants
ACTIVITY = activity; ACTIVITY = activity;
} }
private static void setupWebProxy (boolean enabled) private void setupWebProxy (boolean enabled)
{ {
if (enabled) if (enabled)
{ {
if (webProxy == null) if (webProxy != null)
{
Log.i(TAG,"Setting up Web Proxy on port 8888");
//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());
}
//Settings.System.putString(getContentResolver(), Settings.System.HTTP_PROXY, proxySetting);//enable proxy
// Settings.Secure.putString(getContentResolver(), Settings.Secure.HTTP_PROXY, proxySetting);//enable proxy
}
else
{ {
webProxy.closeSocket();
webProxy = null;
webProxy.setDoSocks(true);
Log.i(TAG,"Web Proxy already running...");
} }
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 else
{ {
Log.i(TAG,"Turning off Socks/Tor routing on Web Proxy"); //Log.i(TAG,"Turning off Socks/Tor routing on Web Proxy");
if (webProxy != null) if (webProxy != null)
{ {
//logNotice("Tor is disabled - browsing is not anonymous!"); //logNotice("Tor is disabled - browsing is not anonymous!");
//webProxy.setDoSocks(false); //webProxy.setDoSocks(false);
webProxy.closeSocket();
webProxy = null;
Log.i(TAG,"WebProxy ServerSocket closed");
} }
} }
} }
public static void reloadConfig () public void reloadConfig ()
{ {
try try
{ {
@ -205,65 +279,39 @@ public class TorService extends Service implements TorConstants
} }
} }
private void shutdownTor () private void killTorProcess ()
{ {
try
{
currentStatus = STATUS_SHUTTING_DOWN;
if (conn == null)
{
initControlConnection ();
}
if (conn != null) if (conn != null)
{
conn.signal("SHUTDOWN");
}
}
catch (Exception e)
{ {
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;
} }
}
private static void killTorProcess ()
{
//doCommand(SHELL_CMD_KILLALL, CHMOD_EXE_VALUE, TOR_BINARY_INSTALL_PATH);
/* try {
if (procTor != null) Thread.sleep(500);
{ } catch (InterruptedException e) {
Log.i(TAG,"shutting down Tor process...");
procTor.destroy();
try {
procTor.waitFor();
}
catch(Exception e2)
{
e2.printStackTrace();
}
int exitStatus = procTor.exitValue();
Log.i(TAG,"Tor exit: " + exitStatus);
}
procTor = null;
}*/
int procId = findProcessId(TorConstants.TOR_BINARY_INSTALL_PATH); int procId = findProcessId(TorConstants.TOR_BINARY_INSTALL_PATH);
if (procId != -1) while (procId != -1)
{ {
Log.i(TAG,"Found Tor PID=" + procId + " - killing now..."); Log.i(TAG,"Found Tor PID=" + procId + " - killing now...");
doCommand(SHELL_CMD_KILLALL, procId + ""); doCommand(SHELL_CMD_KILL, procId + "");
procId = findProcessId(TorConstants.TOR_BINARY_INSTALL_PATH);
} }
conn = null;
} }
@ -316,14 +364,22 @@ public class TorService extends Service implements TorConstants
doCommand(SHELL_CMD_RM,TOR_LOG_PATH); doCommand(SHELL_CMD_RM,TOR_LOG_PATH);
Log.i(TAG,"Starting tor process"); Log.i(TAG,"Starting tor process");
procTor = doCommand(TOR_BINARY_INSTALL_PATH, TOR_COMMAND_LINE_ARGS); doCommand(TOR_BINARY_INSTALL_PATH, TOR_COMMAND_LINE_ARGS);
//Log.i(TAG,"Tor process id=" + procTor.); 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; currentStatus = STATUS_STARTING_UP;
logNotice("Tor is starting up..."); logNotice("Tor is starting up...");
Thread.sleep(2000); Thread.sleep(500);
initControlConnection (); initControlConnection ();
} catch (Exception e) { } catch (Exception e) {
@ -419,7 +475,7 @@ public class TorService extends Service implements TorConstants
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "error: " + e.getMessage(), e); Log.e(TAG, "error: " + e.getMessage());
} }
return child; return child;
@ -436,27 +492,38 @@ public class TorService extends Service implements TorConstants
return null; return null;
} }
public static synchronized void initControlConnection () throws Exception, RuntimeException public void initControlConnection () throws Exception, RuntimeException
{ {
if (conn == null) for (int i = 0; i < 50; i++)
{ {
Log.i(TAG,"Connecting to control port: " + TOR_CONTROL_PORT); try
Socket s = new Socket(IP_LOCALHOST, TOR_CONTROL_PORT); {
conn = TorControlConnection.getConnection(s); Log.i(TAG,"Connecting to control port: " + TOR_CONTROL_PORT);
// conn.authenticate(new byte[0]); // See section 3.2 Socket s = new Socket(IP_LOCALHOST, TOR_CONTROL_PORT);
conn = TorControlConnection.getConnection(s);
Log.i(TAG,"SUCCESS connected to control port"); // 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); File fileCookie = new File(TOR_CONTROL_AUTH_COOKIE);
conn.authenticate(cookie); byte[] cookie = new byte[(int)fileCookie.length()];
new FileInputStream(new File(TOR_CONTROL_AUTH_COOKIE)).read(cookie);
Log.i(TAG,"SUCCESS authenticated to control port"); conn.authenticate(cookie);
addEventHandler(); 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);
}
}
} }
@ -484,17 +551,12 @@ public class TorService extends Service implements TorConstants
} }
private static void getTorStatus () throws IOException private void getTorStatus () throws IOException
{ {
try try
{ {
if (conn == null && (currentStatus == STATUS_STARTING_UP || currentStatus == STATUS_ON))
{
initControlConnection ();
}
if (conn != null) if (conn != null)
@ -522,6 +584,10 @@ public class TorService extends Service implements TorConstants
// Log.i(TAG, "status/circuit-established=" + status); // Log.i(TAG, "status/circuit-established=" + status);
} }
} }
else
{
currentStatus = STATUS_OFF;
}
} }
catch (Exception e) catch (Exception e)
{ {
@ -530,56 +596,22 @@ public class TorService extends Service implements TorConstants
} }
/*
* The recognized signal names are:
"RELOAD" -- Reload configuration information
"SHUTDOWN" -- Start a clean shutdown of the Tor process
"DUMP" -- Write current statistics to the logs
"DEBUG" -- Switch the logs to debugging verbosity
"HALT" -- Stop the Tor process immediately.
*/
public void sendSignal () throws IOException
{
conn.signal("RELOAD");
}
public static void addEventHandler () throws IOException public void addEventHandler () throws IOException
{ {
// We extend NullEventHandler so that we don't need to provide empty // We extend NullEventHandler so that we don't need to provide empty
// implementations for all the events we don't care about. // implementations for all the events we don't care about.
// ... // ...
Log.i(TAG,"adding control port event handler"); Log.i(TAG,"adding control port event handler");
conn.setEventHandler(ACTIVITY);
EventHandler eh = new NullEventHandler()
{ conn.setEvents(Arrays.asList(new String[]{
public void message(String severity, String msg) { "ORCONN", "CIRC", "NOTICE", "ERR"}));
// 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)
{
currentStatus = STATUS_ON;
setupWebProxy(true);
}
}
};
conn.setEventHandler(eh);
conn.setEvents(Arrays.asList(new String[]{
"ORCONN", "CIRC", "INFO", "NOTICE", "ERR"}));
// conn.setEvents(Arrays.asList(new String[]{ // conn.setEvents(Arrays.asList(new String[]{
// "DEBUG", "INFO", "NOTICE", "WARN", "ERR"})); // "DEBUG", "INFO", "NOTICE", "WARN", "ERR"}));
Log.i(TAG,"SUCCESS added control port event handler"); Log.i(TAG,"SUCCESS added control port event handler");
} }
} }