From 9a9823f7e5bf0e46e360ba327ac6514ecd4bb320 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Sun, 9 Jun 2013 02:08:52 -0600 Subject: Introducing the EIP class! Parses eip-service.json for OpenVPN gateways and builds VpnProfiles out of them --- src/se/leap/leapclient/Dashboard.java | 2 + src/se/leap/leapclient/EIP.java | 294 ++++++++++++++++++++++++++++++++ src/se/leap/openvpn/ConfigParser.java | 6 +- src/se/leap/openvpn/OpenVpnService.java | 1 - 4 files changed, 301 insertions(+), 2 deletions(-) create mode 100644 src/se/leap/leapclient/EIP.java diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index dd8ee33..19c635a 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -69,6 +69,8 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf if ( resultCode == RESULT_OK ){ // Configuration done, get our preferences again preferences = getSharedPreferences(ConfigHelper.PREFERENCES_KEY,MODE_PRIVATE); + // Update eip-service local parsing + startService( new Intent(EIP.ACTION_UPDATE_EIP_SERVICE) ); buildDashboard(); } else { diff --git a/src/se/leap/leapclient/EIP.java b/src/se/leap/leapclient/EIP.java new file mode 100644 index 0000000..f86dd08 --- /dev/null +++ b/src/se/leap/leapclient/EIP.java @@ -0,0 +1,294 @@ +package se.leap.leapclient; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Vector; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import se.leap.openvpn.ConfigParser; +import se.leap.openvpn.ConfigParser.ConfigParseError; +import se.leap.openvpn.ProfileManager; +import se.leap.openvpn.VpnProfile; +import android.app.IntentService; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +/** + * @author Sean Leonard + * + */ +public final class EIP extends IntentService { + + public final static String ACTION_UPDATE_EIP_SERVICE = "se.leap.leapclient.UPDATE_EIP_SERVICE"; + + private static Context context; + + // Represents our Provider's eip-service.json + private static JSONObject eipDefinition = null; + + + public EIP(){ + super("LEAPEIP"); + } + + @Override + public void onCreate() { + super.onCreate(); + + context = getApplicationContext(); + + // Inflate our eip-service.json data + try { + eipDefinition = ConfigHelper.getJsonFromSharedPref(ConfigHelper.EIP_SERVICE_KEY); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Override + protected void onHandleIntent(Intent intent) { + // Get our action from the Intent + String action = intent.getAction(); + + if ( action == ACTION_UPDATE_EIP_SERVICE ) + this.updateEIPService(); + } + + private void updateEIPService() { + // TODO this will also fetch new eip-service.json + try { + eipDefinition = ConfigHelper.getJsonFromSharedPref(ConfigHelper.EIP_SERVICE_KEY); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + updateGateways(); + } + + private void updateGateways(){ + JSONArray gatewaysDefined = null; + + // Get our list of gateways + try { + gatewaysDefined = eipDefinition.getJSONArray("gateways"); + } catch (JSONException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + // Walk the list of gateways and inflate them to VPNProfiles + for ( int i=0 ; i < gatewaysDefined.length(); i++ ){ + + JSONObject gw = null; + + try { + gw = gatewaysDefined.getJSONObject(i); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + try { + if ( gw.getJSONObject("capabilities").getJSONArray("transport").toString().contains("openvpn") ){ + // We have an openvpn gateway! + // Now build VPNProfiles and save their UUIDs + // TODO create multiple profiles for each gateway to allow trying e.g. different ports when connections don't complete + new OVPNGateway(gw); + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + private class OVPNGateway { + + // Log tag + private String TAG = "OVPNGateway"; + + // The actual VPN Profile object + private VpnProfile mVpnProfile; + // Our gateway definition from eip-service.json + private JSONObject gateway; + // This holds our OpenVPN options for creating the VPNProfile + // Options get put here in the form that se.leap.openvpn.ConfigParser wants TODO will be gone w/ rewrite + private HashMap>> options = new HashMap>>(); + + + // Constructor to create a gateway by definition + protected OVPNGateway(JSONObject gw){ + // TODO We're going to build 1 profile per gateway, but eventually several + + gateway = gw; + + // Delete VpnProfile for host, if there already is one + // FIXME There is a better way to check settings and update them, instead of destroy/rebuild + // Also, this allows one gateway per hostname entry, so that had better be true from the server! + // TODO Will we define multiple gateways per host, for variable options? or change how .openvpn.VpnProfile works? + ProfileManager vpl = ProfileManager.getInstance(context); + Collection profiles = vpl.getProfiles(); + for (VpnProfile p : profiles){ + try { + if ( p.mName.contains( gateway.getString("host") ) ) + vpl.removeProfile(context, p); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + // Create options HashMap for se.leap.openvpn.ConfigParser + this.parseOptions(); + // Now create the VPNProfile + this.createVPNProfile(); + // Now let's save it in the .openvpn package way + + setUniqueProfileName(vpl); + vpl.addProfile(mVpnProfile); + vpl.saveProfile(context, mVpnProfile); + vpl.saveProfileList(context); + } + + private void setUniqueProfileName(ProfileManager vpl) { + int i=0; + + String newname; + try { + newname = gateway.getString("host"); + while(vpl.getProfileByName(newname)!=null) { + i++; + if(i==1) + newname = getString(R.string.converted_profile); + else + newname = getString(R.string.converted_profile_i,i); + } + + mVpnProfile.mName=newname; + } catch (JSONException e) { + // TODO Auto-generated catch block + Log.v(TAG,"Couldn't read gateway name for profile creation!"); + e.printStackTrace(); + } + } + + // FIXME this whole thing will get rewritten when we modify ConfigParser + // in fact, don't even bother looking, except to debug + private void parseOptions(){ + // TODO we will want to rewrite se.leap.openvpn.ConfigParser soon to be targeted at our use + + // FIXME move these to a common API (& version) definition place, like ProviderAPI or ConfigHelper + String common_options = "openvpn_configuration"; + String remote = "ip_address"; + String ports = "ports"; + String protos = "protocols"; + String capabilities = "capabilities"; + + // FIXME Our gateway definition has keys that are not OpenVPN options... + // We need a hard spec for the eip-service.json and better handling in this class + // Then we can stop dumping all the "capabilities" key:values into our options for parsing + + // Put our common options in + // FIXME quite ugly. We don't need the nested vectors, as we're not byte-reading file input, but we haven't rewritten the parser, yet + + Vector arg = new Vector(); + Vector> args = new Vector>(); + + try { + JSONObject def = (JSONObject) eipDefinition.get(common_options); + Iterator keys = def.keys(); + Vector> value = new Vector>(); + while ( keys.hasNext() ){ + String key = keys.next().toString(); + + arg.add(key); + for ( String word : def.getString(key).split(" ") ) + arg.add(word); + value.add( (Vector) arg.clone() ); + options.put(key, (Vector>) value.clone()); + + value.clear(); + arg.clear(); + } + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + // Now our gateway-specific options + // to hold 'em the way they're wanted for parsing + + // remote:ip_address + try { + arg.add("remote"); + arg.add(gateway.getString(remote)); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + args.add((Vector) arg.clone()); + options.put("remote", (Vector>) args.clone() ); + arg.clear(); + args.clear(); + + // proto:udp||tcp + JSONArray protocolsJSON = null; + arg.add("proto"); + try { + protocolsJSON = gateway.getJSONObject(capabilities).getJSONArray(protos); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + Vector protocols = new Vector(); + for ( int i=0; i) arg.clone()); + options.put("proto", (Vector>) args.clone()); + arg.clear(); + args.clear(); + + + // Now ports...picking one 'cause i say so'... TODO we should have multiple profiles?... + String port = null; + arg.add("port"); + try { + port = gateway.getJSONObject(capabilities).getJSONArray(ports).optString(0); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + arg.add(port); + args.add((Vector) arg.clone()); + options.put("port", (Vector>) args.clone()); + args.clear(); + arg.clear(); + } + + protected void createVPNProfile(){ + // TODO take data from eip-service.json for openvpn gateway definitions and create VPNProfile for each + try { + ConfigParser cp = new ConfigParser(); + cp.setDefinition(options); + VpnProfile vp = cp.convertProfile(); + mVpnProfile = vp; + Log.v(TAG,"Created VPNProfile"); + } catch (ConfigParseError e) { + // FIXME Being here is bad because we didn't get a VpnProfile! + Log.v(TAG,"Error createing VPNProfile"); + e.printStackTrace(); + } + } + } + +} diff --git a/src/se/leap/openvpn/ConfigParser.java b/src/se/leap/openvpn/ConfigParser.java index f57bbae..3d369fa 100644 --- a/src/se/leap/openvpn/ConfigParser.java +++ b/src/se/leap/openvpn/ConfigParser.java @@ -47,6 +47,9 @@ public class ConfigParser { options.get(optionname).add(args); } } + public void setDefinition(HashMap>> args) { + options = args; + } private void checkinlinefile(Vector args, BufferedReader br) throws IOException, ConfigParseError { String arg0 = args.get(0); @@ -247,7 +250,8 @@ public class ConfigParser { // Pull, client, tls-client np.clearDefaults(); - if(options.containsKey("client") || options.containsKey("pull")) { + // XXX we are always client + if(/*options.containsKey("client") || options.containsKey("pull")*/ true) { np.mUsePull=true; options.remove("pull"); options.remove("client"); diff --git a/src/se/leap/openvpn/OpenVpnService.java b/src/se/leap/openvpn/OpenVpnService.java index c745ee3..42c1de8 100644 --- a/src/se/leap/openvpn/OpenVpnService.java +++ b/src/se/leap/openvpn/OpenVpnService.java @@ -35,7 +35,6 @@ import android.net.LocalSocket; import android.net.LocalSocketAddress; import android.net.VpnService; import android.os.Binder; -import android.os.Handler; import android.os.Handler.Callback; import android.os.Build; import android.os.IBinder; -- cgit v1.2.3 From 33338d43e0e83329a7c46807e096b8148e19aff7 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Sun, 9 Jun 2013 04:09:03 -0600 Subject: Quite basic staring and stopping of VPN --- AndroidManifest.xml | 10 +++++- res/layout/eip_overview.xml | 24 +++++++++---- res/values/strings.xml | 1 + src/se/leap/leapclient/ConfigHelper.java | 1 + src/se/leap/leapclient/Dashboard.java | 44 ++++++++++++++---------- src/se/leap/leapclient/EIP.java | 58 ++++++++++++++++++++++++++++++++ src/se/leap/leapclient/Provider.java | 1 + src/se/leap/leapclient/ProviderAPI.java | 14 ++++++-- src/se/leap/openvpn/LaunchVPN.java | 4 +-- src/se/leap/openvpn/VpnProfile.java | 21 ++++++++---- 10 files changed, 142 insertions(+), 36 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 68a1ef1..17f044f 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -153,6 +153,14 @@ android:name="se.leap.leapclient.ConfigurationWizard" android:label="@string/title_activity_configuration_wizard" > + + + + + + + + - + \ No newline at end of file diff --git a/res/layout/eip_overview.xml b/res/layout/eip_overview.xml index 21d4ae3..9cb659f 100644 --- a/res/layout/eip_overview.xml +++ b/res/layout/eip_overview.xml @@ -5,18 +5,29 @@ android:layout_marginTop="10dp" > + + + android:textAppearance="?android:attr/textAppearanceMedium" /> No provider configured Access EIP connection settings Status unknown + EIP: EIP Configure LEAP Add new Provider diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index dd20112..1c2a482 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -53,6 +53,7 @@ public class ConfigHelper { ALLOWED_ANON = "allow_anonymous", MAIN_CERT_KEY = "main_cert", CERT_KEY = "cert", + KEY_KEY = "key", EIP_SERVICE_KEY = "eip", TYPE_OF_CERTIFICATE = "type_of_certificate", ANON_CERTIFICATE = "anon_certificate", diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index 19c635a..31719d9 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -6,7 +6,6 @@ import org.json.JSONException; import org.json.JSONObject; import se.leap.leapclient.ProviderAPIResultReceiver.Receiver; -import se.leap.leapclient.R; import se.leap.openvpn.AboutFragment; import se.leap.openvpn.MainActivity; import android.app.Activity; @@ -26,6 +25,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewStub; import android.widget.CompoundButton; +import android.widget.RelativeLayout; import android.widget.Switch; import android.widget.TextView; import android.widget.Toast; @@ -100,26 +100,32 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf private void buildDashboard() { // Get our provider - provider = Provider.getInstance(); - provider.init( this ); - - // Set provider name in textview - providerNameTV = (TextView) findViewById(R.id.providerName); - providerNameTV.setText(provider.getName()); - providerNameTV.setTextSize(28); // TODO maybe to some calculating, or a marquee? - - // TODO Inflate layout fragments for provider's services - if ( provider.hasEIP() ) - serviceItemEIP(); + provider = Provider.getInstance(); + provider.init( this ); + + // Set provider name in textview + providerNameTV = (TextView) findViewById(R.id.providerName); + providerNameTV.setText(provider.getName()); + providerNameTV.setTextSize(28); // TODO maybe to some calculating, or a marquee? + + if ( provider.hasEIP() /*&& provider.getEIP() != null*/){ + // FIXME let's schedule this, so we're not doing it when we load the app + startService( new Intent(EIP.ACTION_UPDATE_EIP_SERVICE) ); + serviceItemEIP(); + } } private void serviceItemEIP() { - // FIXME Provider service (eip/openvpn) ((ViewStub) findViewById(R.id.eipOverviewStub)).inflate(); // Set our EIP type title eipTypeTV = (TextView) findViewById(R.id.eipType); eipTypeTV.setText(provider.getEIPType()); + // Show our EIP detail + View eipDetail = ((RelativeLayout) findViewById(R.id.eipDetail)); + View eipSettings = findViewById(R.id.eipSettings); + eipSettings.setVisibility(View.GONE); // FIXME too! + eipDetail.setVisibility(View.VISIBLE); // TODO Bind our switch to run our EIP // What happens when our VPN stops running? does it call the listener? @@ -127,12 +133,14 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf eipSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - if ( isChecked ){ - //TODO startVPN(); - } else { - //TODO stopVPN(); + Intent vpnIntent; + if (isChecked){ + vpnIntent = new Intent(EIP.ACTION_START_EIP); + } else { + vpnIntent = new Intent(EIP.ACTION_STOP_EIP); + } + startService(vpnIntent); } - } }); //TODO write our info into the view fragment that will expand with details and a settings button diff --git a/src/se/leap/leapclient/EIP.java b/src/se/leap/leapclient/EIP.java index f86dd08..21cbdfd 100644 --- a/src/se/leap/leapclient/EIP.java +++ b/src/se/leap/leapclient/EIP.java @@ -3,6 +3,7 @@ package se.leap.leapclient; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; +import java.util.NoSuchElementException; import java.util.Vector; import org.json.JSONArray; @@ -11,6 +12,8 @@ import org.json.JSONObject; import se.leap.openvpn.ConfigParser; import se.leap.openvpn.ConfigParser.ConfigParseError; +import se.leap.openvpn.LaunchVPN; +import se.leap.openvpn.OpenVpnManagementThread; import se.leap.openvpn.ProfileManager; import se.leap.openvpn.VpnProfile; import android.app.IntentService; @@ -24,6 +27,8 @@ import android.util.Log; */ public final class EIP extends IntentService { + public final static String ACTION_START_EIP = "se.leap.leapclient.START_EIP"; + public final static String ACTION_STOP_EIP = "se.leap.leapclient.STOP_EIP"; public final static String ACTION_UPDATE_EIP_SERVICE = "se.leap.leapclient.UPDATE_EIP_SERVICE"; private static Context context; @@ -31,6 +36,8 @@ public final class EIP extends IntentService { // Represents our Provider's eip-service.json private static JSONObject eipDefinition = null; + // Our active gateway + private static OVPNGateway activeGateway = null; public EIP(){ super("LEAPEIP"); @@ -58,6 +65,26 @@ public final class EIP extends IntentService { if ( action == ACTION_UPDATE_EIP_SERVICE ) this.updateEIPService(); + else if ( action == ACTION_START_EIP ) + this.startEIP(); + else if ( action == ACTION_STOP_EIP ) + this.stopEIP(); + } + + private void startEIP() { + if (activeGateway==null) + activeGateway = selectGateway(); + + Intent intent = new Intent(this,LaunchVPN.class); + intent.setAction(Intent.ACTION_MAIN); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(LaunchVPN.EXTRA_KEY, activeGateway.mVpnProfile.getUUID().toString() ); + intent.putExtra(LaunchVPN.EXTRA_NAME, activeGateway.mVpnProfile.getName() ); + startActivity(intent); + } + + private void stopEIP() { + OpenVpnManagementThread.stopOpenVPN(); } private void updateEIPService() { @@ -71,6 +98,11 @@ public final class EIP extends IntentService { updateGateways(); } + private OVPNGateway selectGateway() { + // TODO Logic, yay! + return new OVPNGateway("first"); + } + private void updateGateways(){ JSONArray gatewaysDefined = null; @@ -122,6 +154,32 @@ public final class EIP extends IntentService { private HashMap>> options = new HashMap>>(); + // Constructor to load a gateway by name + private OVPNGateway(String name){ + ProfileManager vpl = ProfileManager.getInstance(context); + + try { + + // FIXME ha, this got funny..it will get smart once i'm further... + if ( name == "first" ) { + name = vpl.getProfiles().iterator().next().mName; + } + + mVpnProfile = vpl.getProfileByName(name); + + } catch (NoSuchElementException e) { + + // The gateway we were looking for is not in ProfileList! + updateEIPService(); + + // TODO prompt user to fix config error + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + // Constructor to create a gateway by definition protected OVPNGateway(JSONObject gw){ // TODO We're going to build 1 profile per gateway, but eventually several diff --git a/src/se/leap/leapclient/Provider.java b/src/se/leap/leapclient/Provider.java index 50bd292..4a09bf7 100644 --- a/src/se/leap/leapclient/Provider.java +++ b/src/se/leap/leapclient/Provider.java @@ -124,6 +124,7 @@ public final class Provider implements Serializable { } for (int i=0;i\n"; + cfg+="\n"+ConfigHelper.getStringFromSharedPref(ConfigHelper.KEY_KEY)+"\n\n"; + cfg+="\n"+ConfigHelper.getStringFromSharedPref(ConfigHelper.CERT_KEY)+"\n\n"; + break; case VpnProfile.TYPE_USERPASS_PKCS12: cfg+="auth-user-pass\n"; @@ -492,8 +499,8 @@ public class VpnProfile implements Serializable{ Intent intent = new Intent(context,OpenVpnService.class); if(mAuthenticationType == VpnProfile.TYPE_KEYSTORE || mAuthenticationType == VpnProfile.TYPE_USERPASS_KEYSTORE) { - if(!saveCertificates(context)) - return null; + /*if(!saveCertificates(context)) + return null;*/ } intent.putExtra(prefix + ".ARGV" , buildOpenvpnArgv(context.getCacheDir())); @@ -597,10 +604,10 @@ public class VpnProfile implements Serializable{ //! Return an error if somethign is wrong public int checkProfile(Context context) { - if(mAuthenticationType==TYPE_KEYSTORE || mAuthenticationType==TYPE_USERPASS_KEYSTORE) { +/* if(mAuthenticationType==TYPE_KEYSTORE || mAuthenticationType==TYPE_USERPASS_KEYSTORE) { if(mAlias==null) return R.string.no_keystore_cert_selected; - } + }*/ if(!mUsePull) { if(mIPv4Address == null || cidrToIPAndNetmask(mIPv4Address) == null) -- cgit v1.2.3 From 389dfcdfad555feb1cf212ef9b42626633d5eade Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Sun, 9 Jun 2013 04:31:27 -0600 Subject: Better control and UI feedback for VPN --- src/se/leap/leapclient/ConfigHelper.java | 4 +- src/se/leap/leapclient/Dashboard.java | 138 +++++++++++++++++++++++++++++- src/se/leap/leapclient/EIP.java | 140 ++++++++++++++++++++++++++++++- src/se/leap/openvpn/LaunchVPN.java | 20 ++++- src/se/leap/openvpn/OpenVpnService.java | 15 +++- 5 files changed, 308 insertions(+), 9 deletions(-) diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index 1c2a482..cab5fde 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -73,7 +73,9 @@ public class ConfigHelper { PASSWORD_KEY = "password", ALLOW_REGISTRATION_KEY = "allow_registration", EIP_SERVICE_API_PATH = "config/eip-service.json", - ERRORS_KEY = "errors" + ERRORS_KEY = "errors", + RECEIVER_TAG = "receiverTag", + REQUEST_TAG = "requestTag"; ; final public static String NG_1024 = diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index 31719d9..f10966b 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -8,6 +8,8 @@ import org.json.JSONObject; import se.leap.leapclient.ProviderAPIResultReceiver.Receiver; import se.leap.openvpn.AboutFragment; import se.leap.openvpn.MainActivity; +import se.leap.openvpn.OpenVPN; +import se.leap.openvpn.OpenVPN.StateListener; import android.app.Activity; import android.app.AlertDialog; import android.app.DialogFragment; @@ -19,6 +21,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler; +import android.os.ResultReceiver; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -30,7 +33,7 @@ import android.widget.Switch; import android.widget.TextView; import android.widget.Toast; -public class Dashboard extends Activity implements LogInDialog.LogInDialogInterface, Receiver { +public class Dashboard extends Activity implements LogInDialog.LogInDialogInterface,Receiver,StateListener { protected static final int CONFIGURE_LEAP = 0; @@ -40,8 +43,14 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf private TextView providerNameTV; private TextView eipTypeTV; + private Switch eipSwitch; + private View eipDetail; + private TextView eipStatus; + + private boolean mEipWait = false; public ProviderAPIResultReceiver providerAPI_result_receiver; + private EIPReceiver mEIPReceiver; @Override protected void onCreate(Bundle savedInstanceState) { @@ -62,6 +71,24 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf else startActivityForResult(new Intent(this,ConfigurationWizard.class),CONFIGURE_LEAP); } + + @Override + protected void onStop() { + super.onStop(); + // TODO null provider should only happen before ConfigurationWizard has run, once...better way? + if (provider != null) + if (provider.hasEIP() && provider.getEIPType() == "OpenVPN") + OpenVPN.removeStateListener(this); + } + + @Override + protected void onResume() { + super.onResume(); + // TODO null provider should only happen before ConfigurationWizard has run, once...better way? + if (provider != null) + if (provider.hasEIP() && provider.getEIPType() == "OpenVPN") + OpenVPN.addStateListener(this); + } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data){ @@ -111,36 +138,55 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf if ( provider.hasEIP() /*&& provider.getEIP() != null*/){ // FIXME let's schedule this, so we're not doing it when we load the app startService( new Intent(EIP.ACTION_UPDATE_EIP_SERVICE) ); + if (provider.getEIPType() == "OpenVPN") + OpenVPN.addStateListener(this); serviceItemEIP(); } } private void serviceItemEIP() { + mEIPReceiver = new EIPReceiver(new Handler()); + mEIPReceiver.setReceiver(this); + + Intent intent = new Intent(this,EIP.class); + intent.setAction(EIP.ACTION_IS_EIP_RUNNING); + intent.putExtra(ConfigHelper.RECEIVER_TAG, mEIPReceiver); + startService(intent); + ((ViewStub) findViewById(R.id.eipOverviewStub)).inflate(); // Set our EIP type title eipTypeTV = (TextView) findViewById(R.id.eipType); eipTypeTV.setText(provider.getEIPType()); + // Show our EIP detail - View eipDetail = ((RelativeLayout) findViewById(R.id.eipDetail)); + eipDetail = ((RelativeLayout) findViewById(R.id.eipDetail)); View eipSettings = findViewById(R.id.eipSettings); eipSettings.setVisibility(View.GONE); // FIXME too! eipDetail.setVisibility(View.VISIBLE); + eipStatus = (TextView) findViewById(R.id.eipStatus); // TODO Bind our switch to run our EIP // What happens when our VPN stops running? does it call the listener? - Switch eipSwitch = (Switch) findViewById(R.id.eipSwitch); + eipSwitch = (Switch) findViewById(R.id.eipSwitch); eipSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (!mEipWait){ + // We're gonna have to have some patience! + buttonView.setClickable(false); + mEipWait = true; + Intent vpnIntent; if (isChecked){ vpnIntent = new Intent(EIP.ACTION_START_EIP); } else { vpnIntent = new Intent(EIP.ACTION_STOP_EIP); } + vpnIntent.putExtra(ConfigHelper.RECEIVER_TAG, mEIPReceiver); startService(vpnIntent); } + } }); //TODO write our info into the view fragment that will expand with details and a settings button @@ -333,4 +379,90 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf public static Context getAppContext() { return app; } + + @Override + public void updateState(final String state, final String logmessage, final int localizedResId) { + // Note: "states" are not organized anywhere...collected state strings: + // NOPROCESS,NONETWORK,BYTECOUNT,AUTH_FAILED + some parsing thing ( WAIT(?),AUTH,GET_CONFIG,ASSIGN_IP,CONNECTED(?) ) + // TODO follow-back calls to updateState to find set variable values passed as first param & third param (find those strings...are they all R.string.STATE_* ?) + runOnUiThread(new Runnable() { + + @Override + public void run() { + if (eipStatus != null) { + String prefix = getString(localizedResId) + ":"; + if (state.equals("BYTECOUNT") || state.equals("NOPROCESS")) + prefix = ""; + eipStatus.setText(prefix + logmessage); + } + } + }); + } + + protected class EIPReceiver extends ResultReceiver { + + Dashboard mDashboard; + + protected EIPReceiver(Handler handler){ + super(handler); + } + + public void setReceiver(Dashboard receiver) { + mDashboard = receiver; + } + + @Override + protected void onReceiveResult(int resultCode, Bundle resultData) { + super.onReceiveResult(resultCode, resultData); + + // What were we asking for, again? + String request = resultData.getString(ConfigHelper.REQUEST_TAG); + // Should the EIP switch be on? + mEipWait = true; + boolean checked = false; + + if (request == EIP.ACTION_IS_EIP_RUNNING) { + switch (resultCode){ + case RESULT_OK: + checked = true; + break; + case RESULT_CANCELED: + checked = false; + break; + } + } else if (request == EIP.ACTION_START_EIP) { + switch (resultCode){ + case RESULT_OK: + checked = true; + break; + case RESULT_CANCELED: + checked = false; + break; + } + } else if (request == EIP.ACTION_STOP_EIP) { + switch (resultCode){ + case RESULT_OK: + checked = false; + break; + case RESULT_CANCELED: + checked = true; + break; + } + } else if (request == EIP.EIP_NOTIFICATION) { + switch (resultCode){ + case RESULT_OK: + checked = true; + break; + case RESULT_CANCELED: + checked = false; + break; + } + } + + Switch eipS = ((Switch) mDashboard.findViewById(R.id.eipSwitch)); + eipS.setChecked(checked); + eipS.setClickable(true); + mEipWait = false; + } + } } diff --git a/src/se/leap/leapclient/EIP.java b/src/se/leap/leapclient/EIP.java index 21cbdfd..867805b 100644 --- a/src/se/leap/leapclient/EIP.java +++ b/src/se/leap/leapclient/EIP.java @@ -13,12 +13,21 @@ import org.json.JSONObject; import se.leap.openvpn.ConfigParser; import se.leap.openvpn.ConfigParser.ConfigParseError; import se.leap.openvpn.LaunchVPN; -import se.leap.openvpn.OpenVpnManagementThread; +import se.leap.openvpn.OpenVpnService; +import se.leap.openvpn.OpenVpnService.LocalBinder; import se.leap.openvpn.ProfileManager; import se.leap.openvpn.VpnProfile; + +import android.app.Activity; import android.app.IntentService; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.ServiceConnection; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.os.IBinder; +import android.os.ResultReceiver; import android.util.Log; /** @@ -31,7 +40,17 @@ public final class EIP extends IntentService { public final static String ACTION_STOP_EIP = "se.leap.leapclient.STOP_EIP"; public final static String ACTION_UPDATE_EIP_SERVICE = "se.leap.leapclient.UPDATE_EIP_SERVICE"; + public final static String ACTION_IS_EIP_RUNNING = "se.leap.leapclient.IS_RUNNING"; + + public final static String EIP_NOTIFICATION = "EIP_NOTIFICATION"; + private static Context context; + private static ResultReceiver mReceiver; + // Binder to OpenVpnService for comm ops + private static OpenVpnService mVpnService; + private static boolean mBound = false; + // Used to store actions to "resume" onServiceConnection + private static String mPending = null; // Represents our Provider's eip-service.json private static JSONObject eipDefinition = null; @@ -56,13 +75,27 @@ public final class EIP extends IntentService { // TODO Auto-generated catch block e.printStackTrace(); } + + this.retreiveVpnService(); + } + + @Override + public void onDestroy() { + unbindService(mVpnServiceConn); + mBound = false; + + super.onDestroy(); } @Override protected void onHandleIntent(Intent intent) { // Get our action from the Intent String action = intent.getAction(); + // Get the ResultReceiver, if any + mReceiver = intent.getParcelableExtra(ConfigHelper.RECEIVER_TAG); + if ( action == ACTION_IS_EIP_RUNNING ) + this.isRunning(); if ( action == ACTION_UPDATE_EIP_SERVICE ) this.updateEIPService(); else if ( action == ACTION_START_EIP ) @@ -70,6 +103,70 @@ public final class EIP extends IntentService { else if ( action == ACTION_STOP_EIP ) this.stopEIP(); } + + private void retreiveVpnService() { + Intent bindIntent = new Intent(this,OpenVpnService.class); + bindIntent.setAction(OpenVpnService.RETRIEVE_SERVICE); + bindService(bindIntent, mVpnServiceConn, 0); + } + + private static ServiceConnection mVpnServiceConn = new ServiceConnection() { + + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + LocalBinder binder = (LocalBinder) service; + mVpnService = binder.getService(); + mBound = true; + + if (mReceiver != null && mPending != null) { + + boolean running = mVpnService.isRunning(); + int resultCode = Activity.RESULT_CANCELED; + + if (mPending.equals(ACTION_IS_EIP_RUNNING)) + resultCode = (running) ? Activity.RESULT_OK : Activity.RESULT_CANCELED; + if (mPending.equals(ACTION_START_EIP)) + resultCode = (running) ? Activity.RESULT_OK : Activity.RESULT_CANCELED; + else if (mPending.equals(ACTION_STOP_EIP)) + resultCode = (running) ? Activity.RESULT_CANCELED + : Activity.RESULT_OK; + Bundle resultData = new Bundle(); + resultData.putString(ConfigHelper.REQUEST_TAG, EIP_NOTIFICATION); + mReceiver.send(resultCode, resultData); + + mPending = null; + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + // XXX tell mReceiver!! + mBound = false; + + if (mReceiver != null){ + Bundle resultData = new Bundle(); + resultData.putString(ConfigHelper.REQUEST_TAG, EIP_NOTIFICATION); + mReceiver.send(Activity.RESULT_CANCELED, resultData); + } + } + + }; + + private void isRunning() { + // TODO I don't like that whatever requested this never receives a response + // if OpenVpnService has not been START_SERVICE, though the one place this is used that's okay + if (mBound) { + if (mReceiver != null){ + Bundle resultData = new Bundle(); + resultData.putString(ConfigHelper.REQUEST_TAG, ACTION_IS_EIP_RUNNING); + int resultCode = (mVpnService.isRunning()) ? Activity.RESULT_OK : Activity.RESULT_CANCELED; + mReceiver.send(resultCode, resultData); + } + } else { + mPending = ACTION_IS_EIP_RUNNING; + this.retreiveVpnService(); + } + } private void startEIP() { if (activeGateway==null) @@ -80,11 +177,50 @@ public final class EIP extends IntentService { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra(LaunchVPN.EXTRA_KEY, activeGateway.mVpnProfile.getUUID().toString() ); intent.putExtra(LaunchVPN.EXTRA_NAME, activeGateway.mVpnProfile.getName() ); + intent.putExtra(ConfigHelper.RECEIVER_TAG, mReceiver); startActivity(intent); + // Let's give it 2s to get rolling... TODO there really should be a better way to do this, or it's not needed. + // Read more code in .openvpn package + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + // Bind OpenVpnService for comm ops + if (!mBound){ + mPending = ACTION_START_EIP; + this.retreiveVpnService(); + } else { + if (mReceiver != null) { + Bundle resultData = new Bundle(); + resultData.putString(ConfigHelper.REQUEST_TAG, ACTION_START_EIP); + mReceiver.send(Activity.RESULT_OK, resultData); + } + } } private void stopEIP() { - OpenVpnManagementThread.stopOpenVPN(); + if (mBound){ + mVpnService.onRevoke(); + + /*if (mReceiver != null){ + Bundle resultData = new Bundle(); + resultData.putString(ConfigHelper.REQUEST_TAG, ACTION_STOP_EIP); + mReceiver.send(Activity.RESULT_OK, resultData); + }*/ + } else { + // TODO If OpenVpnService isn't bound, does that really always mean it's not running? + // If it's not running, bindService doesn't work w/o START_SERVICE action, so... + /*mPending = ACTION_STOP_EIP; + this.retreiveVpnService();*/ + } + // Remove this if above comes back + if (mReceiver != null){ + Bundle resultData = new Bundle(); + resultData.putString(ConfigHelper.REQUEST_TAG, ACTION_STOP_EIP); + mReceiver.send(Activity.RESULT_OK, resultData); + } } private void updateEIPService() { diff --git a/src/se/leap/openvpn/LaunchVPN.java b/src/se/leap/openvpn/LaunchVPN.java index 2dcaf17..1df6be9 100644 --- a/src/se/leap/openvpn/LaunchVPN.java +++ b/src/se/leap/openvpn/LaunchVPN.java @@ -19,6 +19,9 @@ package se.leap.openvpn; import java.io.IOException; import java.util.Collection; import java.util.Vector; + +import se.leap.leapclient.ConfigHelper; +import se.leap.leapclient.EIP; import se.leap.leapclient.R; import android.app.Activity; @@ -32,6 +35,7 @@ import android.content.SharedPreferences; import android.net.VpnService; import android.os.Bundle; import android.os.Parcelable; +import android.os.ResultReceiver; import android.preference.PreferenceManager; import android.text.InputType; import android.text.method.PasswordTransformationMethod; @@ -76,6 +80,8 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener { public static final int START_VPN_PROFILE= 70; + // Dashboard, maybe more, want to know! + private ResultReceiver mReceiver; private ProfileManager mPM; private VpnProfile mSelectedProfile; @@ -99,6 +105,9 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener { final Intent intent = getIntent(); final String action = intent.getAction(); + // If something wants feedback, they sent us a Receiver + mReceiver = intent.getParcelableExtra(ConfigHelper.RECEIVER_TAG); + // If the intent is a request to create a shortcut, we'll do that and exit @@ -273,7 +282,11 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener { new startOpenVpnThread().start(); } } else if (resultCode == Activity.RESULT_CANCELED) { - // User does not want us to start, so we just vanish + // User does not want us to start, so we just vanish (well, now we tell our receiver, then vanish) + Bundle resultData = new Bundle(); + // For now, nothing else is calling, so this "request" string is good enough + resultData.putString(ConfigHelper.REQUEST_TAG, EIP.ACTION_START_EIP); + mReceiver.send(RESULT_CANCELED, resultData); finish(); } } @@ -357,6 +370,11 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener { @Override public void run() { VPNLaunchHelper.startOpenVpn(mSelectedProfile, getBaseContext()); + // Tell whom-it-may-concern that we started VPN + Bundle resultData = new Bundle(); + // For now, nothing else is calling, so this "request" string is good enough + resultData.putString(ConfigHelper.REQUEST_TAG, EIP.ACTION_START_EIP); + mReceiver.send(RESULT_OK, resultData); finish(); } diff --git a/src/se/leap/openvpn/OpenVpnService.java b/src/se/leap/openvpn/OpenVpnService.java index 42c1de8..2408483 100644 --- a/src/se/leap/openvpn/OpenVpnService.java +++ b/src/se/leap/openvpn/OpenVpnService.java @@ -20,6 +20,8 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Vector; + +import se.leap.leapclient.Dashboard; import se.leap.leapclient.R; import android.annotation.TargetApi; @@ -44,6 +46,7 @@ import se.leap.openvpn.OpenVPN.StateListener; public class OpenVpnService extends VpnService implements StateListener, Callback { public static final String START_SERVICE = "se.leap.openvpn.START_SERVICE"; + public static final String RETRIEVE_SERVICE = "se.leap.openvpn.RETRIEVE_SERVICE"; private Thread mProcessThread=null; @@ -88,7 +91,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac @Override public IBinder onBind(Intent intent) { String action = intent.getAction(); - if( action !=null && action.equals(START_SERVICE)) + if( action !=null && (action.equals(START_SERVICE) || action.equals(RETRIEVE_SERVICE)) ) return mBinder; else return super.onBind(intent); @@ -222,7 +225,8 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac @Override public int onStartCommand(Intent intent, int flags, int startId) { - if(intent != null && intent.getAction() !=null &&intent.getAction().equals(START_SERVICE)) + if( intent != null && intent.getAction() !=null && + (intent.getAction().equals(START_SERVICE) || intent.getAction().equals(RETRIEVE_SERVICE)) ) return START_NOT_STICKY; @@ -465,6 +469,13 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac mLocalIPv6 = ipv6addr; } + public boolean isRunning() { + if (mStarting == true || mProcessThread != null) + return true; + else + return false; + } + @Override public void updateState(String state,String logmessage, int resid) { // If the process is not running, ignore any state, -- cgit v1.2.3 From 276b8f7dbc7763e284f246a1c538bd06dd8be756 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Sun, 9 Jun 2013 04:36:08 -0600 Subject: Bring up VPN connection log on status line click. Also show it on click of "Configure" button on system notification popup. Also allow toggling of status line. --- res/layout/eip_overview.xml | 4 ++++ src/se/leap/leapclient/Dashboard.java | 23 +++++++++++++++++------ src/se/leap/openvpn/OpenVpnService.java | 6 +++--- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/res/layout/eip_overview.xml b/res/layout/eip_overview.xml index 9cb659f..738c82e 100644 --- a/res/layout/eip_overview.xml +++ b/res/layout/eip_overview.xml @@ -56,6 +56,7 @@ android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignParentTop="true" + android:layout_margin="10dp" android:contentDescription="@string/eip_settings_button_description" android:src="@drawable/ic_sysbar_quicksettings" /> @@ -65,8 +66,11 @@ android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" + android:clickable="true" + android:onClick="showEIPLog" android:text="@string/eip_status" /> + \ No newline at end of file diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index f10966b..965e869 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -7,6 +7,7 @@ import org.json.JSONObject; import se.leap.leapclient.ProviderAPIResultReceiver.Receiver; import se.leap.openvpn.AboutFragment; +import se.leap.openvpn.LogWindow; import se.leap.openvpn.MainActivity; import se.leap.openvpn.OpenVPN; import se.leap.openvpn.OpenVPN.StateListener; @@ -188,13 +189,28 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } } }); - + //TODO write our info into the view fragment that will expand with details and a settings button // TODO set eip overview subview // TODO make eip type clickable, show subview // TODO attach vpn status feedback to eip overview view // TODO attach settings button to something } + + public void toggleEipOverview(View view) { + if (eipDetail.isShown()) + eipDetail.setVisibility(View.GONE); + else + eipDetail.setVisibility(View.VISIBLE); + } + + // FIXME!! I will move to EIPSettingsFragment and begone! + // Also means change onClick property for status line + public void showEIPLog(View view){ + Intent intent = new Intent(getBaseContext(),LogWindow.class); + intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + startActivity(intent); + } @Override public boolean onPrepareOptionsMenu(Menu menu) { @@ -253,11 +269,6 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } } - - @SuppressWarnings("unused") - private void toggleOverview() { - // TODO Expand the one line overview item to show some details - } @Override public void authenticate(String username, String password) { diff --git a/src/se/leap/openvpn/OpenVpnService.java b/src/se/leap/openvpn/OpenVpnService.java index 2408483..a4aa8a3 100644 --- a/src/se/leap/openvpn/OpenVpnService.java +++ b/src/se/leap/openvpn/OpenVpnService.java @@ -175,10 +175,10 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac } PendingIntent getLogPendingIntent() { - // Let the configure Button show the Log - Intent intent = new Intent(getBaseContext(),LogWindow.class); + // Let the configure Button show the Dashboard + Intent intent = new Intent(Dashboard.getAppContext(),Dashboard.class); intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - PendingIntent startLW = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0); + PendingIntent startLW = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); return startLW; -- cgit v1.2.3 From 3fb8205af4d58a5fec930440fe05f766271eec2f Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Sun, 9 Jun 2013 04:37:41 -0600 Subject: Get rid of app's own notification. Only commented out. May want to try showing it until connection success. --- src/se/leap/openvpn/OpenVpnService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/se/leap/openvpn/OpenVpnService.java b/src/se/leap/openvpn/OpenVpnService.java index a4aa8a3..08a5d62 100644 --- a/src/se/leap/openvpn/OpenVpnService.java +++ b/src/se/leap/openvpn/OpenVpnService.java @@ -238,7 +238,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac mProfile = ProfileManager.get(profileUUID); - showNotification("Starting VPN " + mProfile.mName,"Starting VPN " + mProfile.mName, false,0); + //showNotification("Starting VPN " + mProfile.mName,"Starting VPN " + mProfile.mName, false,0); OpenVPN.addStateListener(this); @@ -487,7 +487,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac if("BYTECOUNT".equals(state)) { if(mDisplayBytecount) { - showNotification(logmessage,null,true,mConnecttime); + //showNotification(logmessage,null,true,mConnecttime); } } else { if("CONNECTED".equals(state)) { @@ -501,7 +501,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac // This also mean we are no longer connected, ignore bytecount messages until next // CONNECTED String ticker = getString(resid); - showNotification(getString(resid) +" " + logmessage,ticker,false,0); + //showNotification(getString(resid) +" " + logmessage,ticker,false,0); } } -- cgit v1.2.3 From 98b27656cdb2e76bf966baad0dd8766fd1ebbbdd Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Tue, 18 Jun 2013 20:22:40 -0600 Subject: Remove superfluous comments Unused import removal --- src/se/leap/leapclient/Dashboard.java | 22 +--------------- src/se/leap/leapclient/EIP.java | 47 +---------------------------------- 2 files changed, 2 insertions(+), 67 deletions(-) diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index 965e869..d88d09e 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -65,7 +65,6 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf if(ConfigHelper.shared_preferences == null) ConfigHelper.setSharedPreferences(preferences); - // Check if we have preferences, run configuration wizard if not // TODO We should do a better check for config that this! if (preferences.contains("provider") && preferences.getString(ConfigHelper.PROVIDER_KEY, null) != null) buildDashboard(); @@ -95,14 +94,11 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf protected void onActivityResult(int requestCode, int resultCode, Intent data){ if ( requestCode == CONFIGURE_LEAP ) { if ( resultCode == RESULT_OK ){ - // Configuration done, get our preferences again preferences = getSharedPreferences(ConfigHelper.PREFERENCES_KEY,MODE_PRIVATE); - // Update eip-service local parsing startService( new Intent(EIP.ACTION_UPDATE_EIP_SERVICE) ); buildDashboard(); } else { - // Something went wrong in configuration AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getAppContext()); alertBuilder.setTitle(getResources().getString(R.string.setup_error_title)); alertBuilder @@ -127,16 +123,14 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } private void buildDashboard() { - // Get our provider provider = Provider.getInstance(); provider.init( this ); - // Set provider name in textview providerNameTV = (TextView) findViewById(R.id.providerName); providerNameTV.setText(provider.getName()); providerNameTV.setTextSize(28); // TODO maybe to some calculating, or a marquee? - if ( provider.hasEIP() /*&& provider.getEIP() != null*/){ + if ( provider.hasEIP() ){ // FIXME let's schedule this, so we're not doing it when we load the app startService( new Intent(EIP.ACTION_UPDATE_EIP_SERVICE) ); if (provider.getEIPType() == "OpenVPN") @@ -156,25 +150,20 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf ((ViewStub) findViewById(R.id.eipOverviewStub)).inflate(); - // Set our EIP type title eipTypeTV = (TextView) findViewById(R.id.eipType); eipTypeTV.setText(provider.getEIPType()); - // Show our EIP detail eipDetail = ((RelativeLayout) findViewById(R.id.eipDetail)); View eipSettings = findViewById(R.id.eipSettings); eipSettings.setVisibility(View.GONE); // FIXME too! eipDetail.setVisibility(View.VISIBLE); eipStatus = (TextView) findViewById(R.id.eipStatus); - // TODO Bind our switch to run our EIP - // What happens when our VPN stops running? does it call the listener? eipSwitch = (Switch) findViewById(R.id.eipSwitch); eipSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (!mEipWait){ - // We're gonna have to have some patience! buttonView.setClickable(false); mEipWait = true; @@ -205,7 +194,6 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } // FIXME!! I will move to EIPSettingsFragment and begone! - // Also means change onClick property for status line public void showEIPLog(View view){ Intent intent = new Intent(getBaseContext(),LogWindow.class); intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); @@ -231,7 +219,6 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf @Override public boolean onCreateOptionsMenu(Menu menu) { - // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.client_dashboard, menu); return true; } @@ -239,7 +226,6 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf @Override public boolean onOptionsItemSelected(MenuItem item){ Intent intent; - // Handle item selection switch (item.getItemId()){ case R.id.about_leap: // TODO move se.leap.openvpn.AboutFragment into our package @@ -248,12 +234,8 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf trans.replace(R.id.dashboardLayout, aboutFragment); trans.addToBackStack(null); trans.commit(); - - //intent = new Intent(this,AboutFragment.class); - //startActivity(intent); return true; case R.id.legacy_interface: - // TODO call se.leap.openvpn.MainActivity intent = new Intent(this,MainActivity.class); startActivity(intent); return true; @@ -426,9 +408,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf protected void onReceiveResult(int resultCode, Bundle resultData) { super.onReceiveResult(resultCode, resultData); - // What were we asking for, again? String request = resultData.getString(ConfigHelper.REQUEST_TAG); - // Should the EIP switch be on? mEipWait = true; boolean checked = false; diff --git a/src/se/leap/leapclient/EIP.java b/src/se/leap/leapclient/EIP.java index 867805b..4e23675 100644 --- a/src/se/leap/leapclient/EIP.java +++ b/src/se/leap/leapclient/EIP.java @@ -24,7 +24,6 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.content.SharedPreferences; import android.os.Bundle; import android.os.IBinder; import android.os.ResultReceiver; @@ -39,23 +38,18 @@ public final class EIP extends IntentService { public final static String ACTION_START_EIP = "se.leap.leapclient.START_EIP"; public final static String ACTION_STOP_EIP = "se.leap.leapclient.STOP_EIP"; public final static String ACTION_UPDATE_EIP_SERVICE = "se.leap.leapclient.UPDATE_EIP_SERVICE"; - public final static String ACTION_IS_EIP_RUNNING = "se.leap.leapclient.IS_RUNNING"; - public final static String EIP_NOTIFICATION = "EIP_NOTIFICATION"; private static Context context; private static ResultReceiver mReceiver; - // Binder to OpenVpnService for comm ops private static OpenVpnService mVpnService; private static boolean mBound = false; // Used to store actions to "resume" onServiceConnection private static String mPending = null; - // Represents our Provider's eip-service.json private static JSONObject eipDefinition = null; - // Our active gateway private static OVPNGateway activeGateway = null; public EIP(){ @@ -68,7 +62,6 @@ public final class EIP extends IntentService { context = getApplicationContext(); - // Inflate our eip-service.json data try { eipDefinition = ConfigHelper.getJsonFromSharedPref(ConfigHelper.EIP_SERVICE_KEY); } catch (JSONException e) { @@ -89,9 +82,7 @@ public final class EIP extends IntentService { @Override protected void onHandleIntent(Intent intent) { - // Get our action from the Intent String action = intent.getAction(); - // Get the ResultReceiver, if any mReceiver = intent.getParcelableExtra(ConfigHelper.RECEIVER_TAG); if ( action == ACTION_IS_EIP_RUNNING ) @@ -187,7 +178,6 @@ public final class EIP extends IntentService { // TODO Auto-generated catch block e.printStackTrace(); } - // Bind OpenVpnService for comm ops if (!mBound){ mPending = ACTION_START_EIP; this.retreiveVpnService(); @@ -201,21 +191,8 @@ public final class EIP extends IntentService { } private void stopEIP() { - if (mBound){ + if (mBound) mVpnService.onRevoke(); - - /*if (mReceiver != null){ - Bundle resultData = new Bundle(); - resultData.putString(ConfigHelper.REQUEST_TAG, ACTION_STOP_EIP); - mReceiver.send(Activity.RESULT_OK, resultData); - }*/ - } else { - // TODO If OpenVpnService isn't bound, does that really always mean it's not running? - // If it's not running, bindService doesn't work w/o START_SERVICE action, so... - /*mPending = ACTION_STOP_EIP; - this.retreiveVpnService();*/ - } - // Remove this if above comes back if (mReceiver != null){ Bundle resultData = new Bundle(); resultData.putString(ConfigHelper.REQUEST_TAG, ACTION_STOP_EIP); @@ -242,7 +219,6 @@ public final class EIP extends IntentService { private void updateGateways(){ JSONArray gatewaysDefined = null; - // Get our list of gateways try { gatewaysDefined = eipDefinition.getJSONArray("gateways"); } catch (JSONException e1) { @@ -250,7 +226,6 @@ public final class EIP extends IntentService { e1.printStackTrace(); } - // Walk the list of gateways and inflate them to VPNProfiles for ( int i=0 ; i < gatewaysDefined.length(); i++ ){ JSONObject gw = null; @@ -264,7 +239,6 @@ public final class EIP extends IntentService { try { if ( gw.getJSONObject("capabilities").getJSONArray("transport").toString().contains("openvpn") ){ - // We have an openvpn gateway! // Now build VPNProfiles and save their UUIDs // TODO create multiple profiles for each gateway to allow trying e.g. different ports when connections don't complete new OVPNGateway(gw); @@ -278,14 +252,10 @@ public final class EIP extends IntentService { private class OVPNGateway { - // Log tag private String TAG = "OVPNGateway"; - // The actual VPN Profile object private VpnProfile mVpnProfile; - // Our gateway definition from eip-service.json private JSONObject gateway; - // This holds our OpenVPN options for creating the VPNProfile // Options get put here in the form that se.leap.openvpn.ConfigParser wants TODO will be gone w/ rewrite private HashMap>> options = new HashMap>>(); @@ -304,12 +274,7 @@ public final class EIP extends IntentService { mVpnProfile = vpl.getProfileByName(name); } catch (NoSuchElementException e) { - - // The gateway we were looking for is not in ProfileList! updateEIPService(); - - // TODO prompt user to fix config error - } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -325,7 +290,6 @@ public final class EIP extends IntentService { // Delete VpnProfile for host, if there already is one // FIXME There is a better way to check settings and update them, instead of destroy/rebuild // Also, this allows one gateway per hostname entry, so that had better be true from the server! - // TODO Will we define multiple gateways per host, for variable options? or change how .openvpn.VpnProfile works? ProfileManager vpl = ProfileManager.getInstance(context); Collection profiles = vpl.getProfiles(); for (VpnProfile p : profiles){ @@ -338,11 +302,8 @@ public final class EIP extends IntentService { } } - // Create options HashMap for se.leap.openvpn.ConfigParser this.parseOptions(); - // Now create the VPNProfile this.createVPNProfile(); - // Now let's save it in the .openvpn package way setUniqueProfileName(vpl); vpl.addProfile(mVpnProfile); @@ -415,10 +376,6 @@ public final class EIP extends IntentService { e.printStackTrace(); } - // Now our gateway-specific options - // to hold 'em the way they're wanted for parsing - - // remote:ip_address try { arg.add("remote"); arg.add(gateway.getString(remote)); @@ -431,7 +388,6 @@ public final class EIP extends IntentService { arg.clear(); args.clear(); - // proto:udp||tcp JSONArray protocolsJSON = null; arg.add("proto"); try { @@ -453,7 +409,6 @@ public final class EIP extends IntentService { args.clear(); - // Now ports...picking one 'cause i say so'... TODO we should have multiple profiles?... String port = null; arg.add("port"); try { -- cgit v1.2.3 From a56ecf1b46a158485aa89d2a8f1f5b1b0d819b39 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Tue, 18 Jun 2013 20:32:47 -0600 Subject: Forceful stopping of OpenVPN when trying without bound service --- src/se/leap/leapclient/EIP.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/se/leap/leapclient/EIP.java b/src/se/leap/leapclient/EIP.java index 4e23675..5afffd6 100644 --- a/src/se/leap/leapclient/EIP.java +++ b/src/se/leap/leapclient/EIP.java @@ -13,6 +13,7 @@ import org.json.JSONObject; import se.leap.openvpn.ConfigParser; import se.leap.openvpn.ConfigParser.ConfigParseError; import se.leap.openvpn.LaunchVPN; +import se.leap.openvpn.OpenVpnManagementThread; import se.leap.openvpn.OpenVpnService; import se.leap.openvpn.OpenVpnService.LocalBinder; import se.leap.openvpn.ProfileManager; @@ -193,6 +194,9 @@ public final class EIP extends IntentService { private void stopEIP() { if (mBound) mVpnService.onRevoke(); + else + OpenVpnManagementThread.stopOpenVPN(); + if (mReceiver != null){ Bundle resultData = new Bundle(); resultData.putString(ConfigHelper.REQUEST_TAG, ACTION_STOP_EIP); -- cgit v1.2.3 From 7e98a58eedd638113d447be9c7c2aff8ecfa444e Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Tue, 18 Jun 2013 20:38:24 -0600 Subject: Remove bad,duplicate code from EIP.startEIP() --- src/se/leap/leapclient/EIP.java | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/se/leap/leapclient/EIP.java b/src/se/leap/leapclient/EIP.java index 5afffd6..3831aaf 100644 --- a/src/se/leap/leapclient/EIP.java +++ b/src/se/leap/leapclient/EIP.java @@ -171,24 +171,7 @@ public final class EIP extends IntentService { intent.putExtra(LaunchVPN.EXTRA_NAME, activeGateway.mVpnProfile.getName() ); intent.putExtra(ConfigHelper.RECEIVER_TAG, mReceiver); startActivity(intent); - // Let's give it 2s to get rolling... TODO there really should be a better way to do this, or it's not needed. - // Read more code in .openvpn package - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - if (!mBound){ - mPending = ACTION_START_EIP; - this.retreiveVpnService(); - } else { - if (mReceiver != null) { - Bundle resultData = new Bundle(); - resultData.putString(ConfigHelper.REQUEST_TAG, ACTION_START_EIP); - mReceiver.send(Activity.RESULT_OK, resultData); - } - } + mPending = ACTION_START_EIP; } private void stopEIP() { -- cgit v1.2.3 From e8603d83248591a750d632a35dac125ea7749575 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Tue, 18 Jun 2013 20:57:46 -0600 Subject: Remove superfluous loading of SharedPreferences --- src/se/leap/leapclient/Dashboard.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index d88d09e..d417bb8 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -94,9 +94,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf protected void onActivityResult(int requestCode, int resultCode, Intent data){ if ( requestCode == CONFIGURE_LEAP ) { if ( resultCode == RESULT_OK ){ - preferences = getSharedPreferences(ConfigHelper.PREFERENCES_KEY,MODE_PRIVATE); startService( new Intent(EIP.ACTION_UPDATE_EIP_SERVICE) ); - buildDashboard(); } else { AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getAppContext()); -- cgit v1.2.3 From e2ef783caa56d9d0812c24693a69bcbc23edcbfc Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Tue, 18 Jun 2013 20:58:37 -0600 Subject: Move ConfigurationWizard error result logic to its own method --- src/se/leap/leapclient/Dashboard.java | 46 +++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index d417bb8..392aba5 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -96,30 +96,34 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf if ( resultCode == RESULT_OK ){ startService( new Intent(EIP.ACTION_UPDATE_EIP_SERVICE) ); buildDashboard(); - } else { - AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getAppContext()); - alertBuilder.setTitle(getResources().getString(R.string.setup_error_title)); - alertBuilder - .setMessage(getResources().getString(R.string.setup_error_text)) - .setCancelable(false) - .setPositiveButton(getResources().getString(R.string.setup_error_configure_button), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - startActivityForResult(new Intent(getAppContext(),ConfigurationWizard.class),CONFIGURE_LEAP); - } - }) - .setNegativeButton(getResources().getString(R.string.setup_error_close_button), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - SharedPreferences.Editor prefsEdit = getSharedPreferences(ConfigHelper.PREFERENCES_KEY, MODE_PRIVATE).edit(); - prefsEdit.remove(ConfigHelper.PROVIDER_KEY).commit(); - finish(); - } - }); - } + } else + // FIXME Doesn't take partial config into account + configErrorDialog(); } } + private void configErrorDialog() { + AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getAppContext()); + alertBuilder.setTitle(getResources().getString(R.string.setup_error_title)); + alertBuilder + .setMessage(getResources().getString(R.string.setup_error_text)) + .setCancelable(false) + .setPositiveButton(getResources().getString(R.string.setup_error_configure_button), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + startActivityForResult(new Intent(getAppContext(),ConfigurationWizard.class),CONFIGURE_LEAP); + } + }) + .setNegativeButton(getResources().getString(R.string.setup_error_close_button), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + SharedPreferences.Editor prefsEdit = getSharedPreferences(ConfigHelper.PREFERENCES_KEY, MODE_PRIVATE).edit(); + prefsEdit.remove(ConfigHelper.PROVIDER_KEY).commit(); + finish(); + } + }); + } + private void buildDashboard() { provider = Provider.getInstance(); provider.init( this ); -- cgit v1.2.3 From 79bc86f999d72a9baa548e00deb7c32fcb47e9fe Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Tue, 18 Jun 2013 23:23:24 -0600 Subject: Removed TODO comments, moved to issue tracker --- src/se/leap/leapclient/Dashboard.java | 16 +--------------- src/se/leap/leapclient/EIP.java | 31 +++++-------------------------- 2 files changed, 6 insertions(+), 41 deletions(-) diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index 392aba5..d8b3a19 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -65,7 +65,6 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf if(ConfigHelper.shared_preferences == null) ConfigHelper.setSharedPreferences(preferences); - // TODO We should do a better check for config that this! if (preferences.contains("provider") && preferences.getString(ConfigHelper.PROVIDER_KEY, null) != null) buildDashboard(); else @@ -75,7 +74,6 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf @Override protected void onStop() { super.onStop(); - // TODO null provider should only happen before ConfigurationWizard has run, once...better way? if (provider != null) if (provider.hasEIP() && provider.getEIPType() == "OpenVPN") OpenVPN.removeStateListener(this); @@ -84,7 +82,6 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf @Override protected void onResume() { super.onResume(); - // TODO null provider should only happen before ConfigurationWizard has run, once...better way? if (provider != null) if (provider.hasEIP() && provider.getEIPType() == "OpenVPN") OpenVPN.addStateListener(this); @@ -97,7 +94,6 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf startService( new Intent(EIP.ACTION_UPDATE_EIP_SERVICE) ); buildDashboard(); } else - // FIXME Doesn't take partial config into account configErrorDialog(); } } @@ -130,10 +126,9 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf providerNameTV = (TextView) findViewById(R.id.providerName); providerNameTV.setText(provider.getName()); - providerNameTV.setTextSize(28); // TODO maybe to some calculating, or a marquee? + providerNameTV.setTextSize(28); if ( provider.hasEIP() ){ - // FIXME let's schedule this, so we're not doing it when we load the app startService( new Intent(EIP.ACTION_UPDATE_EIP_SERVICE) ); if (provider.getEIPType() == "OpenVPN") OpenVPN.addStateListener(this); @@ -180,12 +175,6 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } } }); - - //TODO write our info into the view fragment that will expand with details and a settings button - // TODO set eip overview subview - // TODO make eip type clickable, show subview - // TODO attach vpn status feedback to eip overview view - // TODO attach settings button to something } public void toggleEipOverview(View view) { @@ -195,7 +184,6 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf eipDetail.setVisibility(View.VISIBLE); } - // FIXME!! I will move to EIPSettingsFragment and begone! public void showEIPLog(View view){ Intent intent = new Intent(getBaseContext(),LogWindow.class); intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); @@ -230,7 +218,6 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf Intent intent; switch (item.getItemId()){ case R.id.about_leap: - // TODO move se.leap.openvpn.AboutFragment into our package Fragment aboutFragment = new AboutFragment(); FragmentTransaction trans = getFragmentManager().beginTransaction(); trans.replace(R.id.dashboardLayout, aboutFragment); @@ -379,7 +366,6 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf public void updateState(final String state, final String logmessage, final int localizedResId) { // Note: "states" are not organized anywhere...collected state strings: // NOPROCESS,NONETWORK,BYTECOUNT,AUTH_FAILED + some parsing thing ( WAIT(?),AUTH,GET_CONFIG,ASSIGN_IP,CONNECTED(?) ) - // TODO follow-back calls to updateState to find set variable values passed as first param & third param (find those strings...are they all R.string.STATE_* ?) runOnUiThread(new Runnable() { @Override diff --git a/src/se/leap/leapclient/EIP.java b/src/se/leap/leapclient/EIP.java index 3831aaf..d20921c 100644 --- a/src/se/leap/leapclient/EIP.java +++ b/src/se/leap/leapclient/EIP.java @@ -132,7 +132,6 @@ public final class EIP extends IntentService { @Override public void onServiceDisconnected(ComponentName name) { - // XXX tell mReceiver!! mBound = false; if (mReceiver != null){ @@ -145,8 +144,6 @@ public final class EIP extends IntentService { }; private void isRunning() { - // TODO I don't like that whatever requested this never receives a response - // if OpenVpnService has not been START_SERVICE, though the one place this is used that's okay if (mBound) { if (mReceiver != null){ Bundle resultData = new Bundle(); @@ -188,7 +185,6 @@ public final class EIP extends IntentService { } private void updateEIPService() { - // TODO this will also fetch new eip-service.json try { eipDefinition = ConfigHelper.getJsonFromSharedPref(ConfigHelper.EIP_SERVICE_KEY); } catch (JSONException e) { @@ -199,7 +195,8 @@ public final class EIP extends IntentService { } private OVPNGateway selectGateway() { - // TODO Logic, yay! + // TODO Implement gateway selection logic based on TZ or preferences + // TODO will also remove "first" from OVPNGateway constructor return new OVPNGateway("first"); } @@ -226,8 +223,6 @@ public final class EIP extends IntentService { try { if ( gw.getJSONObject("capabilities").getJSONArray("transport").toString().contains("openvpn") ){ - // Now build VPNProfiles and save their UUIDs - // TODO create multiple profiles for each gateway to allow trying e.g. different ports when connections don't complete new OVPNGateway(gw); } } catch (JSONException e) { @@ -243,7 +238,6 @@ public final class EIP extends IntentService { private VpnProfile mVpnProfile; private JSONObject gateway; - // Options get put here in the form that se.leap.openvpn.ConfigParser wants TODO will be gone w/ rewrite private HashMap>> options = new HashMap>>(); @@ -253,7 +247,7 @@ public final class EIP extends IntentService { try { - // FIXME ha, this got funny..it will get smart once i'm further... + // TODO when implementing gateway selection logic if ( name == "first" ) { name = vpl.getProfiles().iterator().next().mName; } @@ -268,15 +262,11 @@ public final class EIP extends IntentService { } } - // Constructor to create a gateway by definition protected OVPNGateway(JSONObject gw){ - // TODO We're going to build 1 profile per gateway, but eventually several gateway = gw; - // Delete VpnProfile for host, if there already is one - // FIXME There is a better way to check settings and update them, instead of destroy/rebuild - // Also, this allows one gateway per hostname entry, so that had better be true from the server! + // Currently deletes VpnProfile for host, if there already is one, and builds new ProfileManager vpl = ProfileManager.getInstance(context); Collection profiles = vpl.getProfiles(); for (VpnProfile p : profiles){ @@ -320,10 +310,7 @@ public final class EIP extends IntentService { } } - // FIXME this whole thing will get rewritten when we modify ConfigParser - // in fact, don't even bother looking, except to debug private void parseOptions(){ - // TODO we will want to rewrite se.leap.openvpn.ConfigParser soon to be targeted at our use // FIXME move these to a common API (& version) definition place, like ProviderAPI or ConfigHelper String common_options = "openvpn_configuration"; @@ -332,13 +319,6 @@ public final class EIP extends IntentService { String protos = "protocols"; String capabilities = "capabilities"; - // FIXME Our gateway definition has keys that are not OpenVPN options... - // We need a hard spec for the eip-service.json and better handling in this class - // Then we can stop dumping all the "capabilities" key:values into our options for parsing - - // Put our common options in - // FIXME quite ugly. We don't need the nested vectors, as we're not byte-reading file input, but we haven't rewritten the parser, yet - Vector arg = new Vector(); Vector> args = new Vector>(); @@ -412,7 +392,6 @@ public final class EIP extends IntentService { } protected void createVPNProfile(){ - // TODO take data from eip-service.json for openvpn gateway definitions and create VPNProfile for each try { ConfigParser cp = new ConfigParser(); cp.setDefinition(options); @@ -420,7 +399,7 @@ public final class EIP extends IntentService { mVpnProfile = vp; Log.v(TAG,"Created VPNProfile"); } catch (ConfigParseError e) { - // FIXME Being here is bad because we didn't get a VpnProfile! + // FIXME We didn't get a VpnProfile! Error handling! Log.v(TAG,"Error createing VPNProfile"); e.printStackTrace(); } -- cgit v1.2.3 From f993d85bcb7e6236960570fef88a22d8d6bcc5e7 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Tue, 18 Jun 2013 23:26:26 -0600 Subject: Refactor EIP.isRunning() --- src/se/leap/leapclient/EIP.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/se/leap/leapclient/EIP.java b/src/se/leap/leapclient/EIP.java index d20921c..5287173 100644 --- a/src/se/leap/leapclient/EIP.java +++ b/src/se/leap/leapclient/EIP.java @@ -144,17 +144,19 @@ public final class EIP extends IntentService { }; private void isRunning() { + Bundle resultData = new Bundle(); + resultData.putString(ConfigHelper.REQUEST_TAG, ACTION_IS_EIP_RUNNING); + int resultCode = Activity.RESULT_CANCELED; if (mBound) { - if (mReceiver != null){ - Bundle resultData = new Bundle(); - resultData.putString(ConfigHelper.REQUEST_TAG, ACTION_IS_EIP_RUNNING); - int resultCode = (mVpnService.isRunning()) ? Activity.RESULT_OK : Activity.RESULT_CANCELED; - mReceiver.send(resultCode, resultData); - } + resultCode = (mVpnService.isRunning()) ? Activity.RESULT_OK : Activity.RESULT_CANCELED; } else { mPending = ACTION_IS_EIP_RUNNING; this.retreiveVpnService(); } + + if (mReceiver != null){ + mReceiver.send(resultCode, resultData); + } } private void startEIP() { -- cgit v1.2.3 From 13fd30cdc0740c60bfeed92c7012bef9a46d4485 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Tue, 18 Jun 2013 23:27:28 -0600 Subject: Rename EIP.OVPNGateway argument and member variable for readability --- src/se/leap/leapclient/EIP.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/se/leap/leapclient/EIP.java b/src/se/leap/leapclient/EIP.java index 5287173..cadb449 100644 --- a/src/se/leap/leapclient/EIP.java +++ b/src/se/leap/leapclient/EIP.java @@ -239,7 +239,7 @@ public final class EIP extends IntentService { private String TAG = "OVPNGateway"; private VpnProfile mVpnProfile; - private JSONObject gateway; + private JSONObject mGateway; private HashMap>> options = new HashMap>>(); @@ -264,9 +264,9 @@ public final class EIP extends IntentService { } } - protected OVPNGateway(JSONObject gw){ + protected OVPNGateway(JSONObject gateway){ - gateway = gw; + mGateway = gateway; // Currently deletes VpnProfile for host, if there already is one, and builds new ProfileManager vpl = ProfileManager.getInstance(context); @@ -295,7 +295,7 @@ public final class EIP extends IntentService { String newname; try { - newname = gateway.getString("host"); + newname = mGateway.getString("host"); while(vpl.getProfileByName(newname)!=null) { i++; if(i==1) @@ -347,7 +347,7 @@ public final class EIP extends IntentService { try { arg.add("remote"); - arg.add(gateway.getString(remote)); + arg.add(mGateway.getString(remote)); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -360,7 +360,7 @@ public final class EIP extends IntentService { JSONArray protocolsJSON = null; arg.add("proto"); try { - protocolsJSON = gateway.getJSONObject(capabilities).getJSONArray(protos); + protocolsJSON = mGateway.getJSONObject(capabilities).getJSONArray(protos); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -381,7 +381,7 @@ public final class EIP extends IntentService { String port = null; arg.add("port"); try { - port = gateway.getJSONObject(capabilities).getJSONArray(ports).optString(0); + port = mGateway.getJSONObject(capabilities).getJSONArray(ports).optString(0); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); -- cgit v1.2.3 From 2249c44ff76949d9ccfabfcb21187eadabc62190 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Wed, 19 Jun 2013 10:10:19 -0600 Subject: Class and method comments and some readability --- src/se/leap/leapclient/Dashboard.java | 40 ++++++++++++++++- src/se/leap/leapclient/EIP.java | 84 ++++++++++++++++++++++++++++++++--- 2 files changed, 116 insertions(+), 8 deletions(-) diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index d8b3a19..bf754ba 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -34,6 +34,12 @@ import android.widget.Switch; import android.widget.TextView; import android.widget.Toast; +/** + * The main user facing Activity of LEAP Android, consisting of status, controls, + * and access to preferences. + * + * @author Sean Leonard + */ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterface,Receiver,StateListener { protected static final int CONFIGURE_LEAP = 0; @@ -98,6 +104,10 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } } + /** + * Dialog shown when encountering a configuration error. Such errors require + * reconfiguring LEAP or aborting the application. + */ private void configErrorDialog() { AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getAppContext()); alertBuilder.setTitle(getResources().getString(R.string.setup_error_title)); @@ -120,6 +130,10 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf }); } + /** + * Inflates permanent UI elements of the View and contains logic for what + * service dependent UI elements to include. + */ private void buildDashboard() { provider = Provider.getInstance(); provider.init( this ); @@ -136,6 +150,9 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } } + /** + * Builds the UI for the EIP service Dashboard component + */ private void serviceItemEIP() { mEIPReceiver = new EIPReceiver(new Handler()); mEIPReceiver.setReceiver(this); @@ -177,6 +194,12 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf }); } + /** + * Expands the EIP Dashboard component for extra details view. + * Called by onClick property in client_dashboard.xml layout. + * + * @param view (Unused) The View calling this method by its onClick property + */ public void toggleEipOverview(View view) { if (eipDetail.isShown()) eipDetail.setVisibility(View.GONE); @@ -184,6 +207,11 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf eipDetail.setVisibility(View.VISIBLE); } + /** + * Launches the se.leap.openvpn.LogWindow Activity showing detailed OpenVPN log + * + * @param view (Unused) The View calling this method by its onClick property + */ public void showEIPLog(View view){ Intent intent = new Intent(getBaseContext(),LogWindow.class); intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); @@ -357,7 +385,12 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf } } - // Used for getting Context when outside of a class extending Context + /** + * For retrieving the base application Context in classes that don't extend + * Android's Activity class + * + * @return Application Context as defined by this for Dashboard instance + */ public static Context getAppContext() { return app; } @@ -380,6 +413,11 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf }); } + /** + * Inner class for handling messages related to EIP status and control requests + * + * @author Sean Leonard + */ protected class EIPReceiver extends ResultReceiver { Dashboard mDashboard; diff --git a/src/se/leap/leapclient/EIP.java b/src/se/leap/leapclient/EIP.java index cadb449..426f435 100644 --- a/src/se/leap/leapclient/EIP.java +++ b/src/se/leap/leapclient/EIP.java @@ -31,8 +31,13 @@ import android.os.ResultReceiver; import android.util.Log; /** + * EIP is the abstract base class for interacting with and managing the Encrypted + * Internet Proxy connection. Connections are started, stopped, and queried through + * this IntentService. + * Contains logic for parsing eip-service.json from the provider, configuring and selecting + * gateways, and controlling {@link .openvpn.OpenVpnService} connections. + * * @author Sean Leonard - * */ public final class EIP extends IntentService { @@ -96,6 +101,10 @@ public final class EIP extends IntentService { this.stopEIP(); } + /** + * Sends an Intent to bind OpenVpnService. + * Used when OpenVpnService isn't bound but might be running. + */ private void retreiveVpnService() { Intent bindIntent = new Intent(this,OpenVpnService.class); bindIntent.setAction(OpenVpnService.RETRIEVE_SERVICE); @@ -143,6 +152,15 @@ public final class EIP extends IntentService { }; + /** + * Attempts to determine if OpenVpnService has an established VPN connection + * through the bound ServiceConnection. If there is no bound service, this + * method will attempt to bind a running OpenVpnService and send + * Activity.RESULT_CANCELED to the ResultReceiver that made the + * request. + * Note: If the request to bind OpenVpnService is successful, the ResultReceiver + * will be notified in {@link onServiceConnected()} + */ private void isRunning() { Bundle resultData = new Bundle(); resultData.putString(ConfigHelper.REQUEST_TAG, ACTION_IS_EIP_RUNNING); @@ -159,6 +177,10 @@ public final class EIP extends IntentService { } } + /** + * Initiates an EIP connection by selecting a gateway and preparing and sending an + * Intent to {@link se.leap.openvpn.LaunchVPN} + */ private void startEIP() { if (activeGateway==null) activeGateway = selectGateway(); @@ -173,6 +195,10 @@ public final class EIP extends IntentService { mPending = ACTION_START_EIP; } + /** + * Disconnects the EIP connection gracefully through the bound service or forcefully + * if there is no bound service. Sends a message to the requesting ResultReceiver. + */ private void stopEIP() { if (mBound) mVpnService.onRevoke(); @@ -186,6 +212,11 @@ public final class EIP extends IntentService { } } + /** + * Loads eip-service.json from SharedPreferences and calls {@link updateGateways()} + * to parse gateway definitions. + * TODO Implement API call to refresh eip-service.json from the provider + */ private void updateEIPService() { try { eipDefinition = ConfigHelper.getJsonFromSharedPref(ConfigHelper.EIP_SERVICE_KEY); @@ -196,12 +227,23 @@ public final class EIP extends IntentService { updateGateways(); } + /** + * Choose a gateway to connect to based on timezone from system locale data + * + * @return The gateway to connect to + */ private OVPNGateway selectGateway() { // TODO Implement gateway selection logic based on TZ or preferences - // TODO will also remove "first" from OVPNGateway constructor + // TODO Implement search through gateways loaded from SharedPreferences + // TODO Remove String arg constructor in favor of findGatewayByName(String) return new OVPNGateway("first"); } + /** + * Walk the list of gateways defined in eip-service.json and parse them into + * OVPNGateway objects. + * TODO Store the OVPNGateways (as Serializable) in SharedPreferences + */ private void updateGateways(){ JSONArray gatewaysDefined = null; @@ -234,6 +276,13 @@ public final class EIP extends IntentService { } } + /** + * OVPNGateway provides objects defining gateways and their options and metadata. + * Each instance contains a VpnProfile for OpenVPN specific data and member + * variables describing capabilities and location + * + * @author Sean Leonard + */ private class OVPNGateway { private String TAG = "OVPNGateway"; @@ -243,13 +292,17 @@ public final class EIP extends IntentService { private HashMap>> options = new HashMap>>(); - // Constructor to load a gateway by name + /** + * Attempts to retrieve a VpnProfile by name and build an OVPNGateway around it. + * FIXME This needs to become a findGatewayByName() method + * + * @param name The hostname of the gateway to inflate + */ private OVPNGateway(String name){ ProfileManager vpl = ProfileManager.getInstance(context); try { - // TODO when implementing gateway selection logic if ( name == "first" ) { name = vpl.getProfiles().iterator().next().mName; } @@ -264,6 +317,12 @@ public final class EIP extends IntentService { } } + /** + * Build a gateway object from a JSON OpenVPN gateway definition in eip-service.json + * and create a VpnProfile belonging to it. + * + * @param gateway The JSON OpenVPN gateway definition to parse + */ protected OVPNGateway(JSONObject gateway){ mGateway = gateway; @@ -290,13 +349,18 @@ public final class EIP extends IntentService { vpl.saveProfileList(context); } - private void setUniqueProfileName(ProfileManager vpl) { + /** + * Attempts to create a unique profile name from the hostname of the gateway + * + * @param profileManager + */ + private void setUniqueProfileName(ProfileManager profileManager) { int i=0; String newname; try { newname = mGateway.getString("host"); - while(vpl.getProfileByName(newname)!=null) { + while(profileManager.getProfileByName(newname)!=null) { i++; if(i==1) newname = getString(R.string.converted_profile); @@ -312,6 +376,9 @@ public final class EIP extends IntentService { } } + /** + * FIXME This method is really the outline of the refactoring needed in se.leap.openvpn.ConfigParser + */ private void parseOptions(){ // FIXME move these to a common API (& version) definition place, like ProviderAPI or ConfigHelper @@ -393,6 +460,9 @@ public final class EIP extends IntentService { arg.clear(); } + /** + * Create and attach the VpnProfile to our gateway object + */ protected void createVPNProfile(){ try { ConfigParser cp = new ConfigParser(); @@ -401,7 +471,7 @@ public final class EIP extends IntentService { mVpnProfile = vp; Log.v(TAG,"Created VPNProfile"); } catch (ConfigParseError e) { - // FIXME We didn't get a VpnProfile! Error handling! + // FIXME We didn't get a VpnProfile! Error handling! and log level Log.v(TAG,"Error createing VPNProfile"); e.printStackTrace(); } -- cgit v1.2.3 From 1739e314e274b0c99b6dbb40ddda3b634affd680 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Thu, 20 Jun 2013 20:41:53 -0600 Subject: Remove update eip definition call causing collision --- src/se/leap/leapclient/Dashboard.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index bf754ba..3c9df56 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -97,7 +97,6 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf protected void onActivityResult(int requestCode, int resultCode, Intent data){ if ( requestCode == CONFIGURE_LEAP ) { if ( resultCode == RESULT_OK ){ - startService( new Intent(EIP.ACTION_UPDATE_EIP_SERVICE) ); buildDashboard(); } else configErrorDialog(); -- cgit v1.2.3 From 304b29d6cb85d710756a56bc9c009429b8407d69 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Thu, 20 Jun 2013 20:42:21 -0600 Subject: Fix bad for loop maths, rookie! --- src/se/leap/leapclient/Provider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/se/leap/leapclient/Provider.java b/src/se/leap/leapclient/Provider.java index 4a09bf7..189c3a8 100644 --- a/src/se/leap/leapclient/Provider.java +++ b/src/se/leap/leapclient/Provider.java @@ -122,7 +122,7 @@ public final class Provider implements Serializable { } catch (Exception e) { // TODO: handle exception } - for (int i=0;i