From d6c35a95905c276a5241bdbf3a01ca89c3c9fd31 Mon Sep 17 00:00:00 2001 From: Arne Schwabe Date: Sat, 9 Feb 2013 16:44:00 +0100 Subject: More refactoring/complete support for openvpn 3 core --HG-- branch : ovpn3 --- src/de/blinkt/openvpn/LogWindow.java | 39 +++++++- src/de/blinkt/openvpn/NetworkSateReceiver.java | 16 ++-- src/de/blinkt/openvpn/OpenVPN.java | 9 +- src/de/blinkt/openvpn/OpenVPNThreadv3.java | 106 +++++++++++++++------ src/de/blinkt/openvpn/OpenVpnManagementThread.java | 39 ++++---- src/de/blinkt/openvpn/OpenVpnService.java | 86 ++++++++++------- 6 files changed, 202 insertions(+), 93 deletions(-) (limited to 'src/de/blinkt') diff --git a/src/de/blinkt/openvpn/LogWindow.java b/src/de/blinkt/openvpn/LogWindow.java index 88615e12..69d1f859 100644 --- a/src/de/blinkt/openvpn/LogWindow.java +++ b/src/de/blinkt/openvpn/LogWindow.java @@ -7,14 +7,17 @@ import android.app.AlertDialog.Builder; import android.app.ListActivity; import android.content.ClipData; import android.content.ClipboardManager; +import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; +import android.content.ServiceConnection; import android.database.DataSetObserver; import android.os.Bundle; import android.os.Handler; import android.os.Handler.Callback; +import android.os.IBinder; import android.os.Message; import android.view.Menu; import android.view.MenuInflater; @@ -30,10 +33,31 @@ import android.widget.Toast; import de.blinkt.openvpn.OpenVPN.LogItem; import de.blinkt.openvpn.OpenVPN.LogListener; import de.blinkt.openvpn.OpenVPN.StateListener; +import de.blinkt.openvpn.OpenVpnService.LocalBinder; public class LogWindow extends ListActivity implements StateListener { private static final int START_VPN_CONFIG = 0; private String[] mBconfig=null; + protected OpenVpnService mService; + private ServiceConnection mConnection = new ServiceConnection() { + + + + @Override + public void onServiceConnected(ComponentName className, + IBinder service) { + // We've bound to LocalService, cast the IBinder and get LocalService instance + LocalBinder binder = (LocalBinder) service; + mService = binder.getService(); + } + + @Override + public void onServiceDisconnected(ComponentName arg0) { + mService =null; + } + + }; + class LogWindowListAdapter implements ListAdapter, LogListener, Callback { @@ -198,6 +222,7 @@ public class LogWindow extends ListActivity implements StateListener { private LogWindowListAdapter ladapter; private TextView mSpeedView; + @Override public boolean onOptionsItemSelected(MenuItem item) { if(item.getItemId()==R.id.clearlog) { @@ -213,7 +238,8 @@ public class LogWindow extends ListActivity implements StateListener { @Override public void onClick(DialogInterface dialog, int which) { ProfileManager.setConntectedVpnProfileDisconnected(getApplicationContext()); - OpenVpnManagementThread.stopOpenVPN(); + if(mService.getManagement()!=null) + mService.getManagement().stopVPN(); } }); @@ -324,6 +350,12 @@ public class LogWindow extends ListActivity implements StateListener { lv.setAdapter(ladapter); mSpeedView = (TextView) findViewById(R.id.speed); + + Intent intent = new Intent(getBaseContext(), OpenVpnService.class); + intent.setAction(OpenVpnService.START_SERVICE); + + bindService(intent, mConnection, Context.BIND_AUTO_CREATE); + } @Override @@ -335,6 +367,8 @@ public class LogWindow extends ListActivity implements StateListener { String prefix=getString(resid) + ":"; if (status.equals("BYTECOUNT") || status.equals("NOPROCESS") ) prefix=""; + if (resid==R.string.unknown_state) + prefix+=status; mSpeedView.setText(prefix + logmessage); } }); @@ -343,8 +377,9 @@ public class LogWindow extends ListActivity implements StateListener { @Override protected void onDestroy() { - super.onDestroy(); + unbindService(mConnection); OpenVPN.removeLogListener(ladapter); + super.onDestroy(); } } diff --git a/src/de/blinkt/openvpn/NetworkSateReceiver.java b/src/de/blinkt/openvpn/NetworkSateReceiver.java index e20c8e52..487639a9 100644 --- a/src/de/blinkt/openvpn/NetworkSateReceiver.java +++ b/src/de/blinkt/openvpn/NetworkSateReceiver.java @@ -11,13 +11,13 @@ import android.preference.PreferenceManager; public class NetworkSateReceiver extends BroadcastReceiver { private int lastNetwork=-1; - private OpenVpnManagementThread mManangement; + private OpenVPNMangement mManangement; private String lastStateMsg=null; - public NetworkSateReceiver(OpenVpnManagementThread managementThread) { + public NetworkSateReceiver(OpenVPNMangement magnagement) { super(); - mManangement = managementThread; + mManangement = magnagement; } @Override @@ -57,15 +57,19 @@ public class NetworkSateReceiver extends BroadcastReceiver { if(networkInfo!=null && networkInfo.getState() == State.CONNECTED) { int newnet = networkInfo.getType(); - if(sendusr1 && lastNetwork!=newnet) - mManangement.reconnect(); + if(sendusr1 && lastNetwork!=newnet) { + if (lastNetwork==-1) + mManangement.resume(); + else + mManangement.reconnect(); + } lastNetwork = newnet; } else if (networkInfo==null) { // Not connected, stop openvpn, set last connected network to no network lastNetwork=-1; if(sendusr1) - mManangement.signalusr1(); + mManangement.pause(); } if(!netstatestring.equals(lastStateMsg)) diff --git a/src/de/blinkt/openvpn/OpenVPN.java b/src/de/blinkt/openvpn/OpenVPN.java index c1616f2d..2ca2d259 100644 --- a/src/de/blinkt/openvpn/OpenVPN.java +++ b/src/de/blinkt/openvpn/OpenVPN.java @@ -173,6 +173,8 @@ public class OpenVPN { return R.string.state_add_routes; else if (state.equals("CONNECTED")) return R.string.state_connected; + else if (state.equals("DISCONNECTED")) + return R.string.state_disconnected; else if (state.equals("RECONNECTING")) return R.string.state_reconnecting; else if (state.equals("EXITING")) @@ -257,7 +259,12 @@ public class OpenVPN { newlogItem(new LogItem(LogItem.ERROR, ressourceId,args)); } - public static void updateByteCount(long in, long out, long diffin, long diffout) { + public static void updateByteCount(long in, long out) { + long lastIn = mlastByteCount[0]; + long lastOut = mlastByteCount[1]; + long diffin = in - lastIn; + long diffout = out - lastOut; + mlastByteCount = new long[] {in,out,diffin,diffout}; for(ByteCountListener bcl:byteCountListener){ bcl.updateByteCount(in, out, diffin,diffout); diff --git a/src/de/blinkt/openvpn/OpenVPNThreadv3.java b/src/de/blinkt/openvpn/OpenVPNThreadv3.java index 36fcc985..39c7640f 100644 --- a/src/de/blinkt/openvpn/OpenVPNThreadv3.java +++ b/src/de/blinkt/openvpn/OpenVPNThreadv3.java @@ -9,8 +9,9 @@ import net.openvpn.ovpn3.ClientAPI_LogInfo; import net.openvpn.ovpn3.ClientAPI_OpenVPNClient; import net.openvpn.ovpn3.ClientAPI_ProvideCreds; import net.openvpn.ovpn3.ClientAPI_Status; +import net.openvpn.ovpn3.ClientAPI_TransportStats; -public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable { +public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable, OpenVPNMangement { static { System.loadLibrary("crypto"); @@ -21,6 +22,34 @@ public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable private VpnProfile mVp; private OpenVpnService mService; + class StatusPoller implements Runnable + { + private long mSleeptime; + + boolean mStopped=false; + + public StatusPoller(long sleeptime) { + mSleeptime=sleeptime; + } + + public void run() { + while(!mStopped) { + try { + Thread.sleep(mSleeptime); + } catch (InterruptedException e) { + } + ClientAPI_TransportStats t = transport_stats(); + long in = t.getBytesIn(); + long out = t.getBytesOut(); + OpenVPN.updateByteCount(in, out); + } + } + + public void stop() { + mStopped=true; + } + } + @Override public void run() { String configstr = mVp.getConfigFile(mService,true); @@ -28,20 +57,25 @@ public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable return; setUserPW(); OpenVPN.logInfo(copyright()); + + StatusPoller statuspoller = new StatusPoller(5000); + new Thread(statuspoller,"Status Poller").start(); + ClientAPI_Status status = connect(); if(status.getError()) { OpenVPN.logError(String.format("connect() error: %s: %s",status.getStatus(),status.getMessage())); } else { - OpenVPN.logInfo(String.format("connect() error: %s: %s",status.getStatus(),status.getMessage())); + OpenVPN.logInfo("OpenVPN3 thread finished"); } + statuspoller.stop(); } - + @Override public boolean tun_builder_set_remote_address(String address, boolean ipv6) { mService.setMtu(1500); return true; } - + @Override public boolean tun_builder_set_mtu(int mtu) { mService.setMtu(mtu); @@ -52,36 +86,39 @@ public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable mService.addDNS(address); return true; } - + @Override public boolean tun_builder_add_route(String address, int prefix_length, boolean ipv6) { + if (address.equals("remote_host")) + return false; + if(ipv6) mService.addRoutev6(address + "/" + prefix_length); else mService.addRoute(new CIDRIP(address, prefix_length)); return true; } - + @Override public boolean tun_builder_add_search_domain(String domain) { mService.setDomain(domain); return true; } - + @Override public int tun_builder_establish() { return mService.openTun().detachFd(); } - + @Override public boolean tun_builder_set_session_name(String name) { OpenVPN.logInfo("We should call this session" + name); return true; } - - + + @Override public boolean tun_builder_add_address(String address, int prefix_length, boolean ipv6) { @@ -91,20 +128,20 @@ public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable mService.setLocalIPv6(address+ "/" + prefix_length); return true; } - + @Override public boolean tun_builder_new() { - + return true; } - + @Override public boolean tun_builder_reroute_gw(String server_address, boolean server_address_ipv6, boolean ipv4, boolean ipv6, long flags) { // ignore return true; } - + @Override public boolean tun_builder_exclude_route(String address, int prefix_length, boolean ipv6) { @@ -114,15 +151,15 @@ public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable private boolean setConfig(String vpnconfig) { - + ClientAPI_Config config = new ClientAPI_Config(); if(mVp.getPasswordPrivateKey()!=null) config.setPrivateKeyPassword(mVp.getPasswordPrivateKey()); - + config.setContent(vpnconfig); config.setTunPersist(mVp.mPersistTun); config.setExternalPkiAlias("extpki"); - + ClientAPI_EvalConfig ec = eval_config(config); if(ec.getExternalPki()) { OpenVPN.logError("OpenVPN seem to think as external PKI"); @@ -135,7 +172,7 @@ public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable return true; } } - + @Override public void external_pki_cert_request(ClientAPI_ExternalPKICertRequest certreq) { OpenVPN.logError("EXT PKI CERT"); @@ -145,15 +182,14 @@ public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable certreq.setErrorText("Error in pki cert request"); return; } - + certreq.setSupportingChain(ks[0]); certreq.setCert(ks[1]); certreq.setError(false); } - + @Override public void external_pki_sign_request(ClientAPI_ExternalPKISignRequest signreq) { - OpenVPN.logError("EXT PKI Sign"); signreq.setSig(mVp.getSignedData(signreq.getData())); } @@ -170,9 +206,8 @@ public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable @Override public boolean socket_protect(int socket) { boolean b= mService.protect(socket); - OpenVPN.logInfo("protect from v3: " + b); - return true; - + return b; + } public OpenVPNThreadv3(OpenVpnService openVpnService, VpnProfile vp) { @@ -186,7 +221,7 @@ public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable String logmsg =arg0.getText(); while (logmsg.endsWith("\n")) logmsg = logmsg.substring(0, logmsg.length()-1); - + OpenVPN.logInfo(logmsg); } @@ -197,9 +232,26 @@ public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable OpenVPN.logError(String.format("EVENT(Error): %s: %s",event.getName(),event.getInfo())); } - public void stopVPN() { + + // When a connection is close to timeout, the core will call this + // method. If it returns false, the core will disconnect with a + // CONNECTION_TIMEOUT event. If true, the core will enter a PAUSE + // state. + + @Override + public boolean pause_on_connection_timeout() { + OpenVPN.logInfo("pause on connection timeout?! "); + return true; + } + + public boolean stopVPN() { stop(); - + return true; + } + + @Override + public void reconnect() { + reconnect(1); } } diff --git a/src/de/blinkt/openvpn/OpenVpnManagementThread.java b/src/de/blinkt/openvpn/OpenVpnManagementThread.java index 538079e8..e4528132 100644 --- a/src/de/blinkt/openvpn/OpenVpnManagementThread.java +++ b/src/de/blinkt/openvpn/OpenVpnManagementThread.java @@ -7,28 +7,18 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; import java.util.LinkedList; import java.util.Locale; import java.util.Vector; -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; - import android.content.SharedPreferences; import android.net.LocalServerSocket; import android.net.LocalSocket; -import android.os.Build; import android.os.ParcelFileDescriptor; import android.preference.PreferenceManager; -import android.util.Base64; import android.util.Log; -public class OpenVpnManagementThread implements Runnable { +public class OpenVpnManagementThread implements Runnable, OpenVPNMangement { private static final String TAG = "openvpn"; private LocalSocket mSocket; @@ -36,8 +26,6 @@ public class OpenVpnManagementThread implements Runnable { private OpenVpnService mOpenVPNService; private LinkedList mFDList=new LinkedList(); private int mBytecountinterval=2; - private long mLastIn=0; - private long mLastOut=0; private LocalServerSocket mServerSocket; private boolean mReleaseHold=true; private boolean mWaitingForRelease=false; @@ -284,13 +272,7 @@ public class OpenVpnManagementThread implements Runnable { long in = Long.parseLong(argument.substring(0, comma)); long out = Long.parseLong(argument.substring(comma+1)); - long diffin = in - mLastIn; - long diffout = out - mLastOut; - - mLastIn=in; - mLastOut=out; - - OpenVPN.updateByteCount(in,out,diffin, diffout); + OpenVPN.updateByteCount(in,out); } @@ -448,7 +430,7 @@ public class OpenVpnManagementThread implements Runnable { } - public static boolean stopOpenVPN() { + private static boolean stopOpenVPN() { boolean sendCMD=false; for (OpenVpnManagementThread mt: active){ mt.managmentCommand("signal SIGINT\n"); @@ -481,4 +463,19 @@ public class OpenVpnManagementThread implements Runnable { managmentCommand(signed_string); managmentCommand("\nEND\n"); } + + @Override + public void pause() { + signalusr1(); + } + + @Override + public void resume() { + releaseHold(); + } + + @Override + public boolean stopVPN() { + return stopOpenVPN(); + } } diff --git a/src/de/blinkt/openvpn/OpenVpnService.java b/src/de/blinkt/openvpn/OpenVpnService.java index 675e44b9..d5d75589 100644 --- a/src/de/blinkt/openvpn/OpenVpnService.java +++ b/src/de/blinkt/openvpn/OpenVpnService.java @@ -62,9 +62,6 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac private CIDRIP mLocalIP=null; - private OpenVpnManagementThread mManagementThread; - - private Thread mSocketManagerThread; private int mMtu; private String mLocalIPv6=null; private NetworkSateReceiver mNetworkStateReceiver; @@ -90,6 +87,8 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac private final IBinder mBinder = new LocalBinder(); private boolean mOvpn3; private OpenVPNThreadv3 mOpenVPN3; + private Thread mSocketManagerThread; + private OpenVPNMangement mManagement; public class LocalBinder extends Binder { public OpenVpnService getService() { @@ -109,10 +108,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac @Override public void onRevoke() { - if(!mOvpn3) - OpenVpnManagementThread.stopOpenVPN(); - else - mOpenVPN3.stopVPN(); + mManagement.stopVPN(); endVpnService(); } @@ -126,6 +122,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac OpenVPN.logBuilderConfig(null); OpenVPN.removeStateListener(this); OpenVPN.removeByteCountListener(this); + unregisterNetworkStateReceiver(); ProfileManager.setConntectedVpnProfileDisconnected(this); if(!mStarting) { stopForeground(!mNotificationalwaysVisible); @@ -180,9 +177,9 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac // PRIORITY_MIN == -2 setpriority.invoke(nbuilder, -2 ); - Method setUsesChronometer = nbuilder.getClass().getMethod("setPriority", boolean.class); + Method setUsesChronometer = nbuilder.getClass().getMethod("setUsesChronometer", boolean.class); setUsesChronometer.invoke(nbuilder,true); - + /* PendingIntent cancelconnet=null; nbuilder.addAction(android.R.drawable.ic_menu_close_clear_cancel, @@ -240,14 +237,20 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac } - void registerNetworkStateReceiver() { + void registerNetworkStateReceiver(OpenVPNMangement magnagement) { // Registers BroadcastReceiver to track network connection changes. IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); - mNetworkStateReceiver = new NetworkSateReceiver(mManagementThread); + mNetworkStateReceiver = new NetworkSateReceiver(magnagement); this.registerReceiver(mNetworkStateReceiver, filter); } - + void unregisterNetworkStateReceiver() { + if(mNetworkStateReceiver!=null) + this.unregisterReceiver(mNetworkStateReceiver); + mNetworkStateReceiver=null; + } + + @Override public int onStartCommand(Intent intent, int flags, int startId) { @@ -274,19 +277,27 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac showNotification("Starting VPN " + mProfile.mName,"Starting VPN " + mProfile.mName, false,0,LEVEL_NOTCONNECTED); - - // Set a flag that we are starting a new VPN mStarting=true; // Stop the previous session by interrupting the thread. - if(OpenVpnManagementThread.stopOpenVPN()){ - // an old was asked to exit, wait 2s + if(mManagement!=null && mManagement.stopVPN()) + // an old was asked to exit, wait 1s + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + + + if(mOpenVPN3!=null) { + mOpenVPN3.stopVPN(); try { Thread.sleep(1000); } catch (InterruptedException e) { } + } + if (mProcessThread!=null) { mProcessThread.interrupt(); try { @@ -299,18 +310,19 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac // Open the Management Interface - LocalServerSocket mgmtsocket = openManagmentInterface(8); - - if(mgmtsocket!=null) { - // start a Thread that handles incoming messages of the managment socket - mManagementThread=new OpenVpnManagementThread(mProfile,mgmtsocket,this); - mSocketManagerThread = new Thread(mManagementThread,"OpenVPNMgmtThread"); - mSocketManagerThread.start(); - OpenVPN.logInfo("started Socket Thread"); - registerNetworkStateReceiver(); + if(!mOvpn3) { + LocalServerSocket mgmtsocket = openManagmentInterface(8); + + if(mgmtsocket!=null) { + // start a Thread that handles incoming messages of the managment socket + OpenVpnManagementThread ovpnmgmthread = new OpenVpnManagementThread(mProfile,mgmtsocket,this); + mSocketManagerThread = new Thread(ovpnmgmthread,"OpenVPNMgmtThread"); + mSocketManagerThread.start(); + mManagement= ovpnmgmthread; + OpenVPN.logInfo("started Socket Thread"); + } } - // Start a new session by creating a new thread. SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); @@ -318,19 +330,21 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac Runnable processThread; if(mOvpn3) { - mOpenVPN3 = new OpenVPNThreadv3(this,mProfile); - processThread = mOpenVPN3; + mManagement = mOpenVPN3; + } else { - processThread = new OpenVPNThread(this, argv,nativelibdir); - } + mProcessThread = new Thread(processThread, "OpenVPNProcessThread"); mProcessThread.start(); + registerNetworkStateReceiver(mManagement); + + ProfileManager.setConnectedVpnProfile(this, mProfile); return START_NOT_STICKY; @@ -339,7 +353,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac @Override public void onDestroy() { if (mProcessThread != null) { - mManagementThread.managmentCommand("signal SIGINT\n"); + mManagement.stopVPN(); mProcessThread.interrupt(); } @@ -500,13 +514,13 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac public void setMtu(int mtu) { mMtu=mtu; } - + public void setLocalIP(CIDRIP cdrip) { mLocalIP=cdrip; } - - + + public void setLocalIP(String local, String netmask,int mtu, String mode) { mLocalIP = new CIDRIP(local, netmask); mMtu = mtu; @@ -597,7 +611,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac } } - public OpenVpnManagementThread getManagementThread() { - return mManagementThread; + public OpenVPNMangement getManagement() { + return mManagement; } } -- cgit v1.2.3