[tor-commits] [orbot/master] Improve VPN service support - fix network switching handling

n8fr8 at torproject.org n8fr8 at torproject.org
Fri Apr 3 17:04:09 UTC 2015


commit 75426bb9e25d11fa84636481aac59094eec41b26
Author: Nathan Freitas <nathan at freitas.net>
Date:   Fri Apr 3 12:27:59 2015 -0400

    Improve VPN service support - fix network switching handling
    We now refresh the VPN and tun2socks interfaces when the network
    type switches, and we do so in a way that does not cause traffic to leak.
    The new interface is established before we close the old one.
---
 res/values/arrays.xml                              |   13 +-
 res/values/strings.xml                             |   13 +-
 src/org/torproject/android/OrbotConstants.java     |    2 +-
 src/org/torproject/android/OrbotMainActivity.java  |  180 ++++++++++++++++----
 src/org/torproject/android/service/TorService.java |  134 +++++++++++----
 .../torproject/android/vpn/OrbotVpnService.java    |  157 ++++++++++-------
 6 files changed, 359 insertions(+), 140 deletions(-)

diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index fb0a7c3..00eb3a4 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -36,9 +36,16 @@
 		<item>ru</item>
 		
 		
-		
-		
-		
+	</string-array>
+	
+	<string-array name="bridge_options">
+	    <item>Obfs4 (Recommended)</item>
+	    <item>Obfs3</item>
+	    <item>ScrambleSuit</item>
+	    <item>Tunnel through Azure</item>
+	    <item>Tunnel through Amazon</item>
+	    <item>Tunnel through Google</item>
+	    <item></item>
 	</string-array>
     
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 92e1e35..e76ce28 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -315,15 +315,16 @@
   
   <string name="bridges_updated">Bridges Updated</string>
   
-  <string name="restart_orbot_to_use_this_bridge_">"Restart Orbot to use these bridges: "</string>
+  <string name="restart_orbot_to_use_this_bridge_">Please restart Orbot to enable the changes</string>
   
   <string name="menu_qr">QR Codes</string>
   
-  <string name="if_your_mobile_network_actively_blocks_tor_you_can_use_a_tor_bridge_to_access_the_network_another_way_to_get_bridges_is_to_send_an_email_to_bridges_torproject_org_please_note_that_you_must_send_the_email_using_an_address_from_one_of_the_following_email_providers_riseup_gmail_or_yahoo_">If your mobile network actively blocks Tor, you can use a Tor Bridge to access the network.\n\nYou can get a bridge address from https://bridges.torproject.org or scan a bridge QR code from a friend.\n\nAnother way to get bridges is to send an email to bridges at torproject.org. Please note that you must send the email using an address from one of the following email providers: Riseup, Gmail or Yahoo.</string>
+  <string name="if_your_mobile_network_actively_blocks_tor_you_can_use_a_tor_bridge_to_access_the_network_another_way_to_get_bridges_is_to_send_an_email_to_bridges_torproject_org_please_note_that_you_must_send_the_email_using_an_address_from_one_of_the_following_email_providers_riseup_gmail_or_yahoo_">If your mobile network actively blocks Tor, you can use a Tor Bridge to access the network.\n\nYou can get a bridge address from https://bridges.torproject.org, by emailing bridges at torproject.org, or by scanning a bridge QR code.</string>
   
   <string name="bridge_mode">Bridge Mode</string>
   
-  <string name="get_bridges">Get Bridges</string>
+  <string name="get_bridges_email">Email</string>
+  <string name="get_bridges_web">Web</string>
   
   <string name="activate">Activate</string>
   
@@ -332,4 +333,10 @@
   <string name="you_can_enable_all_apps_on_your_device_to_run_through_the_tor_network_using_the_vpn_feature_of_android_">You can enable all apps on your device to run through the Tor network using the VPN feature of Android.\n\n*WARNING* This is a new, experimental feature and in some cases may not start automatically, or may stop. It should NOT be used for anonymity, and ONLY used for getting through firewalls and filters.</string>
   
   <string name="send_email">Send Email</string>
+  
+  <string name="you_must_get_a_bridge_address_by_email_web_or_from_a_friend_once_you_have_this_address_please_paste_it_into_the_bridges_preference_in_orbot_s_setting_and_restart_">You must can a bridge address by email, web or by scanning a bridge QR code. Once you have this address, please paste it into the \"Bridges\" preference in Orbot\'s setting and restart.</string>
+  
+  <string name="install_orweb">Install Orweb</string>
+  
+  <string name="standard_browser">Standard Browser</string>
 </resources>
diff --git a/src/org/torproject/android/OrbotConstants.java b/src/org/torproject/android/OrbotConstants.java
index 745ace4..fa67d92 100644
--- a/src/org/torproject/android/OrbotConstants.java
+++ b/src/org/torproject/android/OrbotConstants.java
@@ -16,7 +16,7 @@ public interface OrbotConstants {
 	//path to check Tor against
 	public final static String URL_TOR_CHECK = "https://check.torproject.org";
 	
-    public final static String URL_TOR_BRIDGES = "https://bridges.torproject.org";
+    public final static String URL_TOR_BRIDGES = "https://bridges.torproject.org/bridges?transport=";
     
     public final static String NEWLINE = "\n";
     
diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java
index be05d69..2e22fb2 100644
--- a/src/org/torproject/android/OrbotMainActivity.java
+++ b/src/org/torproject/android/OrbotMainActivity.java
@@ -661,6 +661,8 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon
 		setResult(RESULT_OK);
 		
 		mBtnBridges.setChecked(true);
+		
+		enableBridges(true);
 	}
 
 	private boolean showWizard = true;
@@ -707,7 +709,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon
               .setIcon(R.drawable.onion32)
 		      .setTitle(R.string.install_apps_)
 		      .setMessage(R.string.it_doesn_t_seem_like_you_have_orweb_installed_want_help_with_that_or_should_we_just_open_the_browser_)
-		      .setPositiveButton(android.R.string.ok, new Dialog.OnClickListener ()
+		      .setPositiveButton(R.string.install_orweb, new Dialog.OnClickListener ()
 		      {
 
 				@Override
@@ -720,7 +722,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon
 				}
 		    	  
 		      })
-		      .setNegativeButton(android.R.string.no, new Dialog.OnClickListener ()
+		      .setNegativeButton(R.string.standard_browser, new Dialog.OnClickListener ()
 		      {
 
 				@Override
@@ -860,41 +862,56 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon
 	        new AlertDialog.Builder(this)
 	        .setTitle(R.string.bridge_mode)
 	        .setView(view)
-	        .setNeutralButton(R.string.get_bridges, new Dialog.OnClickListener ()
-	        {
-	
-				@Override
-				public void onClick(DialogInterface dialog, int which) {
-					
-					//openBrowser(URL_TOR_BRIDGES);
-	
-					sendGetBridgeEmail();
-				}
-	
-	       	 
-	        })
-	        .setPositiveButton(R.string.activate, new Dialog.OnClickListener ()
-	        {
-	
-				@Override
-				public void onClick(DialogInterface dialog, int which) {
-					
-					enableBridges (true);
-					
-				}
-	
-	       	 
-	        })
-	        .setNegativeButton(android.R.string.cancel, new Dialog.OnClickListener()
+	        .setItems(R.array.bridge_options, new DialogInterface.OnClickListener() {
+               public void onClick(DialogInterface dialog, int which) {
+               // The 'which' argument contains the index position
+               // of the selected item
+            	   
+            	   switch (which)
+            	   {
+            	   case 0: //obfs 4;
+            		   showGetBridgePrompt("obfs4");
+            		   
+            		   break;
+            	   case 1: //obfs3
+            		   showGetBridgePrompt("obfs3");
+            		   
+            		   break;
+            	   case 2: //scramblesuit
+            		   showGetBridgePrompt("scramblesuit");
+            		   
+            		   break;
+            	   case 3: //azure
+            		   mPrefs.edit().putString(OrbotConstants.PREF_BRIDGES_LIST,"2").commit();
+            		   enableBridges(true);
+            		   
+            		   break;
+            	   case 4: //amazon
+            		   mPrefs.edit().putString(OrbotConstants.PREF_BRIDGES_LIST,"1").commit();
+            		   enableBridges(true);
+            		   
+            		   break;
+            	   case 5: //google
+            		   mPrefs.edit().putString(OrbotConstants.PREF_BRIDGES_LIST,"0").commit();
+            		   enableBridges(true);
+            		   
+            		   break;
+            		  
+            	   }
+            	   
+               }
+           }).setNegativeButton(android.R.string.cancel, new Dialog.OnClickListener()
 	        {
 	        	@Override
 				public void onClick(DialogInterface dialog, int which) {
 					
-	            	mBtnBridges.setChecked(false);
+	            	//mBtnBridges.setChecked(false);
 					
 				}
 	        })
 	        .show();
+	        
+	       
         }
         else
         {
@@ -903,13 +920,72 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon
         
     }
     
-    private void sendGetBridgeEmail ()
+    private void showGetBridgePrompt (final String type)
+    {
+    	LayoutInflater li = LayoutInflater.from(this);
+        View view = li.inflate(R.layout.layout_diag, null); 
+        
+        TextView versionName = (TextView)view.findViewById(R.id.diaglog);
+        versionName.setText(R.string.you_must_get_a_bridge_address_by_email_web_or_from_a_friend_once_you_have_this_address_please_paste_it_into_the_bridges_preference_in_orbot_s_setting_and_restart_);    
+        
+        new AlertDialog.Builder(this)
+        .setTitle(R.string.bridge_mode)
+        .setView(view)
+        .setNegativeButton(android.R.string.cancel, new Dialog.OnClickListener()
+        {
+        	@Override
+			public void onClick(DialogInterface dialog, int which) {
+				
+            	//mBtnBridges.setChecked(false);
+				
+			}
+        })
+        .setNeutralButton(R.string.get_bridges_email, new Dialog.OnClickListener ()
+        {
+
+			@Override
+			public void onClick(DialogInterface dialog, int which) {
+				
+
+				sendGetBridgeEmail(type);
+
+			}
+
+       	 
+        })
+        .setPositiveButton(R.string.get_bridges_web, new Dialog.OnClickListener ()
+        {
+
+			@Override
+			public void onClick(DialogInterface dialog, int which) {
+				
+				openBrowser(URL_TOR_BRIDGES + type);
+
+			}
+
+       	 
+        }).show();
+    }
+    
+    private void sendGetBridgeEmail (String type)
     {
     	Intent intent = new Intent(Intent.ACTION_SEND);
     	intent.setType("message/rfc822");
 		intent.putExtra(Intent.EXTRA_EMAIL  , new String[]{"bridges at torproject.org"});
-    	intent.putExtra(Intent.EXTRA_SUBJECT, "Tor Bridge Request");
-
+		
+		if (type != null)
+		{
+	    	intent.putExtra(Intent.EXTRA_SUBJECT, "get transport " + type);
+	    	intent.putExtra(Intent.EXTRA_TEXT, "get transport " + type);
+	    	
+		}
+		else
+		{
+			intent.putExtra(Intent.EXTRA_SUBJECT, "get bridges");
+			intent.putExtra(Intent.EXTRA_TEXT, "get bridges");
+			
+		}
+		
     	startActivity(Intent.createChooser(intent, getString(R.string.send_email)));
     }
     
@@ -917,10 +993,45 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon
     {
 
 		Editor edit = mPrefs.edit();
-		edit.putBoolean("pref_bridges_enabled", enable);
+		edit.putBoolean(OrbotConstants.PREF_BRIDGES_ENABLED, enable);
 		edit.commit();
 		
 		updateSettings();
+		
+		if (torStatus == TorServiceConstants.STATUS_ON)
+		{
+			String bridgeList = mPrefs.getString(OrbotConstants.PREF_BRIDGES_LIST,null);
+			if (bridgeList != null && bridgeList.length() > 0)
+			{
+				try
+				{
+					//do auto restart
+					stopTor ();
+					
+					mHandler.postDelayed(new Runnable () {
+						
+						public void run ()
+						{
+							try 
+							{
+								startTor();
+							}
+							catch (Exception e)
+							{
+								Log.e(TAG,"can't start orbot",e);
+							}
+						}
+					}, 2000);
+				}
+				catch (Exception e)
+				{
+					Log.e(TAG,"can't stop orbot",e);
+				}
+			}
+			
+		}
+				
+		
     }
     
     public void promptStartVpnService ()
@@ -1160,7 +1271,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon
         //here we update the UI which is a bit sloppy and mixed up code wise
         //might be best to just call updateStatus() instead of directly manipulating UI in this method - yep makes sense
         imgStatus.setImageResource(R.drawable.torstarting);
-    //    lblStatus.setText(getString(R.string.status_starting_up));
+        lblStatus.setText(getString(R.string.status_starting_up));
         
         //we send a message here to the progressDialog i believe, but we can clarify that shortly
         Message msg = mHandler.obtainMessage(TorServiceConstants.ENABLE_TOR_MSG);
@@ -1168,7 +1279,6 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon
         mHandler.sendMessage(msg);
       
         
-        
     }
     
     //now we stop Tor! amazing!
diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java
index 9529d6d..cae1697 100644
--- a/src/org/torproject/android/service/TorService.java
+++ b/src/org/torproject/android/service/TorService.java
@@ -96,7 +96,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
     private int mPortHTTP = 8118;
     private int mPortSOCKS = 9050;
     
-    private int mVpnProxyPort = 7231;
+    private int mVpnProxyPort = 9099;
     
     private static final int NOTIFY_ID = 1;
     private static final int TRANSPROXY_NOTIFY_ID = 2;
@@ -1475,6 +1475,18 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
            
         }
         
+        public void refreshVpnProxy () {
+            
+        	debug ("refreshing VPN Proxy");
+        	
+            Intent intent = new Intent(TorService.this, OrbotVpnService.class);
+            intent.setAction("refresh");
+            startService(intent);
+           
+        }
+        
+        
+        
         public void clearVpnProxy ()
         {   
         	debug ("clearing VPN Proxy");
@@ -1911,6 +1923,31 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
             return false;
         }
         
+        public void setTorNetworkEnabled (final boolean isEnabled)
+        {
+
+        	
+        	//it is possible to not have a connection yet, and someone might try to newnym
+            if (conn != null)
+            {
+                new Thread ()
+                {
+                    public void run ()
+                    {
+                        try { 
+                            
+                            conn.setConf("DisableNetwork", isEnabled ? "0" : "1");
+                        	
+                        }
+                        catch (Exception ioe){
+                            debug("error requesting newnym: " + ioe.getLocalizedMessage());
+                        }
+                    }
+                }.start();
+            }
+        	
+        }
+        
         public void newIdentity () 
         {
             //it is possible to not have a connection yet, and someone might try to newnym
@@ -2048,52 +2085,75 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
             final ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
             final NetworkInfo netInfo = cm.getActiveNetworkInfo();
 
+            boolean newConnectivityState = false;
+            
             if(netInfo != null && netInfo.isConnected()) {
                 // WE ARE CONNECTED: DO SOMETHING
-                mConnectivity = true;
+            	newConnectivityState = true;
             }   
             else {
                 // WE ARE NOT: DO SOMETHING ELSE
-                mConnectivity = false;
+            	newConnectivityState = false;
             }
             
-            if (doNetworKSleep)
+            //is this a change in state?
+            if (mConnectivity != newConnectivityState)
             {
-                try {
-                    updateConfiguration("DisableNetwork", mConnectivity ? "0" : "1", false);
-                    
-                    if (mCurrentStatus != STATUS_OFF)
-                    {
-                        if (!mConnectivity)
-                        {
-                            logNotice(context.getString(R.string.no_network_connectivity_putting_tor_to_sleep_));
-                            showToolbarNotification(getString(R.string.no_internet_connection_tor),NOTIFY_ID,R.drawable.ic_stat_tor_off);
-                            
-                        }
-                        else
-                        {
-                            logNotice(context.getString(R.string.network_connectivity_is_good_waking_tor_up_));
-                            showToolbarNotification(getString(R.string.status_activated),NOTIFY_ID,R.drawable.ic_stat_tor);
-
-                            if (mHasRoot && mEnableTransparentProxy && mTransProxyNetworkRefresh)
-                            {
-                                
-                                 Shell shell = Shell.startRootShell();
-                         
-                                disableTransparentProxy(shell);
-                                enableTransparentProxy(shell);
-                                
-                                shell.close();
-                            }
-                            
-                        }
-                    }
-                    
-                } catch (Exception e) {
-                    logException ("error updating state after network restart",e);
-                }
+            
+	            if (doNetworKSleep)
+	            {
+	                try {
+	                    
+	                    setTorNetworkEnabled (mConnectivity);
+	                    
+	                    if (mCurrentStatus != STATUS_OFF)
+	                    {
+	                        if (!mConnectivity)
+	                        {
+	                            logNotice(context.getString(R.string.no_network_connectivity_putting_tor_to_sleep_));
+	                            showToolbarNotification(getString(R.string.no_internet_connection_tor),NOTIFY_ID,R.drawable.ic_stat_tor_off);
+	                            
+	                        }
+	                        else
+	                        {
+	                            logNotice(context.getString(R.string.network_connectivity_is_good_waking_tor_up_));
+	                            showToolbarNotification(getString(R.string.status_activated),NOTIFY_ID,R.drawable.ic_stat_tor);
+	
+	                            if (mHasRoot && mEnableTransparentProxy && mTransProxyNetworkRefresh)
+	                            {
+	                                
+	                                 Shell shell = Shell.startRootShell();
+	                         
+	                                disableTransparentProxy(shell);
+	                                enableTransparentProxy(shell);
+	                                
+	                                shell.close();
+	                            }
+	                            
+	                        }
+	                    }
+	                    
+	                    saveConfiguration();
+	                    
+	                } catch (Exception e) {
+	                    logException ("error updating state after network restart",e);
+	                }
+	            }
+	            
+	            if (mUseVPN && mConnectivity &&  (mCurrentStatus != STATUS_OFF)) //we need to turn on VPN here so the proxy is running
+	            {
+	            	setTorNetworkEnabled (false);
+	            	refreshVpnProxy();
+	            	setTorNetworkEnabled (true);
+	            	
+	            	
+	            }
             }
             
+            mConnectivity = newConnectivityState;
+            
+
+            
         }
     };
 
diff --git a/src/org/torproject/android/vpn/OrbotVpnService.java b/src/org/torproject/android/vpn/OrbotVpnService.java
index 2127562..b495937 100644
--- a/src/org/torproject/android/vpn/OrbotVpnService.java
+++ b/src/org/torproject/android/vpn/OrbotVpnService.java
@@ -57,6 +57,10 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
     
     private final static int VPN_MTU = 1500;
     
+    private final static boolean isLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
+    
+    private boolean isRestart = false;
+    
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
 
@@ -76,7 +80,7 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
 	        // Stop the previous session by interrupting the thread.
 	        if (mThreadVPN == null || (!mThreadVPN.isAlive()))
 	        {
-	        	boolean isLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
+	        	
 	        	if (!isLollipop)
 	        		startSocksBypass();
 	        	
@@ -89,6 +93,13 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
     		if (mHandler != null)
     			mHandler.postDelayed(new Runnable () { public void run () { stopSelf(); }}, 1000);
     	}
+    	else if (action.equals("refresh"))
+    	{
+    		if (!isLollipop)
+    			startSocksBypass();
+    		
+    		setupTun2Socks();
+    	}
      
         
         return START_NOT_STICKY;
@@ -102,6 +113,12 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
             {
         
                 try {
+                	
+                	if (mSocksProxyServer != null)
+                	{
+                		stopSocksBypass ();
+                	}
+                	
                     mSocksProxyServer = new ProxyServer(new ServerAuthenticatorNone(null, null));
                     ProxyServer.setVpnService(OrbotVpnService.this);
                     mSocksProxyServer.start(mSocksProxyPort, 5, InetAddress.getLocalHost());
@@ -115,10 +132,20 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
         
     }
 
+    private void stopSocksBypass ()
+    {
+
+        if (mSocksProxyServer != null){
+            mSocksProxyServer.stop();
+            mSocksProxyServer = null;
+        }
+        
+        
+    }
+    
     @Override
     public void onDestroy() {
     	stopVPN();
-    	
     }
     
     private void stopVPN ()
@@ -126,10 +153,7 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
 
         Tun2Socks.Stop();
         
-        if (mSocksProxyServer != null){
-            mSocksProxyServer.stop();
-            mSocksProxyServer = null;
-        }
+        stopSocksBypass ();
         
         if (mInterface != null){
             try
@@ -167,54 +191,64 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
     		
     		public void run ()
     		{
-		    	if (mInterface == null)
-		    	{
-		    		try
+	    		try
+		        {
+	    			
+		    		// Set the locale to English (or probably any other language that^M
+		            // uses Hindu-Arabic (aka Latin) numerals).^M
+		            // We have found that VpnService.Builder does something locale-dependent^M
+		            // internally that causes errors when the locale uses its own numerals^M
+		            // (i.e., Farsi and Arabic).^M
+		    		Locale.setDefault(new Locale("en"));
+		    		
+		    		//String localhost = InetAddress.getLocalHost().getHostAddress();
+		    		
+		    		String vpnName = "OrbotVPN";
+		    		String virtualGateway = "10.0.0.1";
+		        	String virtualIP = "10.0.0.2";
+		        	String virtualNetMask = "255.255.255.0";
+		        	String localSocks = "127.0.0.1" + ':' + TorServiceConstants.PORT_SOCKS_DEFAULT;
+		        	String localDNS = "10.0.0.1" + ':' + TorServiceConstants.TOR_DNS_PORT_DEFAULT;
+		        	
+		        	
+			        Builder builder = new Builder();
+			        
+			        builder.setMtu(VPN_MTU);
+			        builder.addAddress(virtualGateway,28);
+			        builder.setSession(vpnName);	 
+			        builder.addRoute("0.0.0.0",0);	 
+			      //  builder.addDnsServer("8.8.8.8");
+			        
+			        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
 			        {
-		    			
-			    		// Set the locale to English (or probably any other language that^M
-			            // uses Hindu-Arabic (aka Latin) numerals).^M
-			            // We have found that VpnService.Builder does something locale-dependent^M
-			            // internally that causes errors when the locale uses its own numerals^M
-			            // (i.e., Farsi and Arabic).^M
-			    		Locale.setDefault(new Locale("en"));
-			    		
-			    		//String localhost = InetAddress.getLocalHost().getHostAddress();
-			    		
-			    		String vpnName = "OrbotVPN";
-			    		String virtualGateway = "10.0.0.1";
-			        	String virtualIP = "10.0.0.2";
-			        	String virtualNetMask = "255.255.255.0";
-			        	String localSocks = "127.0.0.1" + ':' + TorServiceConstants.PORT_SOCKS_DEFAULT;
-			        	String localDNS = "10.0.0.1" + ':' + TorServiceConstants.TOR_DNS_PORT_DEFAULT;
-			        	
-			        	
-				        Builder builder = new Builder();
-				        
-				        builder.setMtu(VPN_MTU);
-				        builder.addAddress(virtualGateway,28);
-				        builder.setSession(vpnName);	 
-				        builder.addRoute("0.0.0.0",0);	 
-				      //  builder.addDnsServer("8.8.8.8");
-				        
-				        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
-				        {
-				        	doLollipopAppRouting(builder);
-				        }
-				        
-				         // Create a new interface using the builder and save the parameters.
-				        mInterface = builder.setSession(mSessionName)
-				                .setConfigureIntent(mConfigureIntent)
-				                .establish();
-				        	    
-			        	Tun2Socks.Start(mInterface, VPN_MTU, virtualIP, virtualNetMask, localSocks , localDNS , true);
+			        	doLollipopAppRouting(builder);
 			        }
-			        catch (Exception e)
+			        
+			         // Create a new interface using the builder and save the parameters.
+			        ParcelFileDescriptor newInterface = builder.setSession(mSessionName)
+			                .setConfigureIntent(mConfigureIntent)
+			                .establish();
+			        	    
+			        if (mInterface != null)
 			        {
-			        	Log.d(TAG,"tun2Socks has stopped",e);
+			        	isRestart = true;
+			        	
+			        	Tun2Socks.Stop();
+			        	mInterface.close();
+			        	
 			        }
-		    	}
-    		}
+			        
+
+		        	mInterface = newInterface;
+			        
+		        	Tun2Socks.Start(mInterface, VPN_MTU, virtualIP, virtualNetMask, localSocks , localDNS , true);
+		        }
+		        catch (Exception e)
+		        {
+		        	Log.d(TAG,"tun2Socks has stopped",e);
+		        }
+	    	}
+    		
     	};
     	
     	mThreadVPN.start();
@@ -222,22 +256,23 @@ public class OrbotVpnService extends VpnService implements Handler.Callback {
     
     @TargetApi(Build.VERSION_CODES.LOLLIPOP)
 	private void doLollipopAppRouting (Builder builder) throws NameNotFoundException
-    {
-
-        
-    	builder.addDisallowedApplication("org.torproject.android");
-    
-        
+    {    
+    	builder.addDisallowedApplication("org.torproject.android");   
     }
     
     @Override
     public void onRevoke() {
     
-    	SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); 
-        prefs.edit().putBoolean("pref_vpn", false).commit();
-        
-    	stopVPN();
-
+    	if (!isRestart)
+    	{
+	    	SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); 
+	        prefs.edit().putBoolean("pref_vpn", false).commit();      
+	    	stopVPN();
+	    	
+    	}
+    	
+    	isRestart = false;
+    	
         super.onRevoke();
     }
     





More information about the tor-commits mailing list