summaryrefslogtreecommitdiff
path: root/src/se/leap/leapclient
diff options
context:
space:
mode:
authorSean Leonard <meanderingcode@aetherislands.net>2013-06-09 04:31:27 -0600
committerSean Leonard <meanderingcode@aetherislands.net>2013-06-20 18:46:39 -0600
commit389dfcdfad555feb1cf212ef9b42626633d5eade (patch)
tree4485c33699424bbb20f94e610171fa1ef01b08e2 /src/se/leap/leapclient
parent33338d43e0e83329a7c46807e096b8148e19aff7 (diff)
Better control and UI feedback for VPN
Diffstat (limited to 'src/se/leap/leapclient')
-rw-r--r--src/se/leap/leapclient/ConfigHelper.java4
-rw-r--r--src/se/leap/leapclient/Dashboard.java138
-rw-r--r--src/se/leap/leapclient/EIP.java140
3 files changed, 276 insertions, 6 deletions
diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java
index 1c2a482a..cab5fdee 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 31719d90..f10966b2 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 21cbdfd5..867805bd 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() {