diff options
Diffstat (limited to 'app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java')
-rw-r--r-- | app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java | 328 |
1 files changed, 80 insertions, 248 deletions
diff --git a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java index 1e2ccba3..a9cc4f18 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java +++ b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java @@ -5,45 +5,27 @@ package de.blinkt.openvpn.core; -import android.annotation.SuppressLint; import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.Signature; import android.os.Build; import android.os.HandlerThread; import android.os.Message; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; -import android.util.Log; -import java.io.ByteArrayInputStream; -import java.io.DataOutputStream; import java.io.File; -import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringWriter; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.FormatFlagsConversionMismatchException; import java.util.LinkedList; import java.util.Locale; -import java.util.UnknownFormatConversionException; +import java.util.Queue; import java.util.Vector; +import java.util.concurrent.ConcurrentLinkedQueue; -import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.R; +import de.blinkt.openvpn.VpnProfile; public class VpnStatus { - public static LinkedList<LogItem> logbuffer; + private static final LinkedList<LogItem> logbuffer; private static Vector<LogListener> logListener; private static Vector<StateListener> stateListener; @@ -55,7 +37,14 @@ public class VpnStatus { private static int mLastStateresid = R.string.state_noprocess; - private static long mlastByteCount[] = {0, 0, 0, 0}; + private static HandlerThread mHandlerThread; + + private static String mLastConnectedVPNUUID; + static boolean readFileLog =false; + final static java.lang.Object readFileLock = new Object(); + + + public static TrafficHistory trafficHistory; public static void logException(LogLevel ll, String context, Exception e) { StringWriter sw = new StringWriter(); @@ -79,6 +68,9 @@ public class VpnStatus { static final int MAXLOGENTRIES = 1000; + public static boolean isVPNActive() { + return mLastLevel != ConnectionStatus.LEVEL_AUTH_FAILED && !(mLastLevel == ConnectionStatus.LEVEL_NOTCONNECTED); + } public static String getLastCleanLogMessage(Context c) { String message = mLaststatemsg; @@ -111,6 +103,10 @@ public class VpnStatus { if (status.equals("NOPROCESS")) return message; + if (mLastStateresid == R.string.state_waitconnectretry) { + return c.getString(R.string.state_waitconnectretry, mLaststatemsg); + } + String prefix = c.getString(mLastStateresid); if (mLastStateresid == R.string.unknown_state) message = status + message; @@ -122,28 +118,38 @@ public class VpnStatus { } public static void initLogCache(File cacheDir) { + mHandlerThread = new HandlerThread("LogFileWriter", Thread.MIN_PRIORITY); + mHandlerThread.start(); + mLogFileHandler = new LogFileHandler(mHandlerThread.getLooper()); + + Message m = mLogFileHandler.obtainMessage(LogFileHandler.LOG_INIT, cacheDir); mLogFileHandler.sendMessage(m); } public static void flushLog() { - mLogFileHandler.sendEmptyMessage(LogFileHandler.FLUSH_TO_DISK); + if (mLogFileHandler!=null) + mLogFileHandler.sendEmptyMessage(LogFileHandler.FLUSH_TO_DISK); } - public enum ConnectionStatus { - LEVEL_CONNECTED, - LEVEL_VPNPAUSED, - LEVEL_CONNECTING_SERVER_REPLIED, - LEVEL_CONNECTING_NO_SERVER_REPLY_YET, - LEVEL_NONETWORK, - LEVEL_NOTCONNECTED, - LEVEL_START, - LEVEL_AUTH_FAILED, - LEVEL_WAITING_FOR_USER_INPUT, - UNKNOWN_LEVEL + public static void setConnectedVPNProfile(String uuid) { + mLastConnectedVPNUUID = uuid; + for (StateListener sl: stateListener) + sl.setConnectedVPN(uuid); } + + public static String getLastConnectedVPNProfile() + { + return mLastConnectedVPNUUID; + } + + public static void setTrafficHistory(TrafficHistory trafficHistory) { + VpnStatus.trafficHistory = trafficHistory; + } + + public enum LogLevel { INFO(2), ERROR(-2), @@ -163,14 +169,17 @@ public class VpnStatus { public static LogLevel getEnumByValue(int value) { switch (value) { - case 1: - return INFO; case 2: + return INFO; + case -2: return ERROR; - case 3: + case 1: return WARNING; + case 3: + return VERBOSE; case 4: return DEBUG; + default: return null; } @@ -178,218 +187,36 @@ public class VpnStatus { } // keytool -printcert -jarfile de.blinkt.openvpn_85.apk - public static final byte[] officalkey = {-58, -42, -44, -106, 90, -88, -87, -88, -52, -124, 84, 117, 66, 79, -112, -111, -46, 86, -37, 109}; - public static final byte[] officaldebugkey = {-99, -69, 45, 71, 114, -116, 82, 66, -99, -122, 50, -70, -56, -111, 98, -35, -65, 105, 82, 43}; - public static final byte[] amazonkey = {-116, -115, -118, -89, -116, -112, 120, 55, 79, -8, -119, -23, 106, -114, -85, -56, -4, 105, 26, -57}; - public static final byte[] fdroidkey = {-92, 111, -42, -46, 123, -96, -60, 79, -27, -31, 49, 103, 11, -54, -68, -27, 17, 2, 121, 104}; + static final byte[] officalkey = {-58, -42, -44, -106, 90, -88, -87, -88, -52, -124, 84, 117, 66, 79, -112, -111, -46, 86, -37, 109}; + static final byte[] officaldebugkey = {-99, -69, 45, 71, 114, -116, 82, 66, -99, -122, 50, -70, -56, -111, 98, -35, -65, 105, 82, 43}; + static final byte[] amazonkey = {-116, -115, -118, -89, -116, -112, 120, 55, 79, -8, -119, -23, 106, -114, -85, -56, -4, 105, 26, -57}; + static final byte[] fdroidkey = {-92, 111, -42, -46, 123, -96, -60, 79, -27, -31, 49, 103, 11, -54, -68, -27, 17, 2, 121, 104}; private static ConnectionStatus mLastLevel = ConnectionStatus.LEVEL_NOTCONNECTED; - private static final LogFileHandler mLogFileHandler; + private static LogFileHandler mLogFileHandler; static { logbuffer = new LinkedList<>(); logListener = new Vector<>(); stateListener = new Vector<>(); byteCountListener = new Vector<>(); - - HandlerThread mHandlerThread = new HandlerThread("LogFileWriter", Thread.MIN_PRIORITY); - mHandlerThread.start(); - mLogFileHandler = new LogFileHandler(mHandlerThread.getLooper()); + trafficHistory = new TrafficHistory(); logInformation(); } - public static class LogItem implements Parcelable { - private Object[] mArgs = null; - private String mMessage = null; - private int mRessourceId; - // Default log priority - LogLevel mLevel = LogLevel.INFO; - private long logtime = System.currentTimeMillis(); - private int mVerbosityLevel = -1; - - private LogItem(int ressourceId, Object[] args) { - mRessourceId = ressourceId; - mArgs = args; - } - - public LogItem(LogLevel level, int verblevel, String message) { - mMessage = message; - mLevel = level; - mVerbosityLevel = verblevel; - } - - @Override - public int describeContents() { - return 0; - } - - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeArray(mArgs); - dest.writeString(mMessage); - dest.writeInt(mRessourceId); - dest.writeInt(mLevel.getInt()); - dest.writeInt(mVerbosityLevel); - - dest.writeLong(logtime); - } - - public LogItem(Parcel in) { - mArgs = in.readArray(Object.class.getClassLoader()); - mMessage = in.readString(); - mRessourceId = in.readInt(); - mLevel = LogLevel.getEnumByValue(in.readInt()); - mVerbosityLevel = in.readInt(); - logtime = in.readLong(); - } - - public static final Parcelable.Creator<LogItem> CREATOR - = new Parcelable.Creator<LogItem>() { - public LogItem createFromParcel(Parcel in) { - return new LogItem(in); - } - - public LogItem[] newArray(int size) { - return new LogItem[size]; - } - }; - - public LogItem(LogLevel loglevel, int ressourceId, Object... args) { - mRessourceId = ressourceId; - mArgs = args; - mLevel = loglevel; - } - - - public LogItem(LogLevel loglevel, String msg) { - mLevel = loglevel; - mMessage = msg; - } - - - public LogItem(LogLevel loglevel, int ressourceId) { - mRessourceId = ressourceId; - mLevel = loglevel; - } - - public String getString(Context c) { - try { - if (mMessage != null) { - return mMessage; - } else { - if (c != null) { - if (mRessourceId == R.string.mobile_info) - return getMobileInfoString(c); - if (mArgs == null) - return c.getString(mRessourceId); - else - return c.getString(mRessourceId, mArgs); - } else { - String str = String.format(Locale.ENGLISH, "Log (no context) resid %d", mRessourceId); - if (mArgs != null) - str += TextUtils.join("|", mArgs); - - return str; - } - } - } catch (UnknownFormatConversionException e) { - if (c != null) - throw new UnknownFormatConversionException(e.getLocalizedMessage() + getString(null)); - else - throw e; - } catch (java.util.FormatFlagsConversionMismatchException e) { - if (c != null) - throw new FormatFlagsConversionMismatchException(e.getLocalizedMessage() + getString(null), e.getConversion()); - else - throw e; - } - - } - - public LogLevel getLogLevel() { - return mLevel; - } - - // The lint is wrong here - @SuppressLint("StringFormatMatches") - private String getMobileInfoString(Context c) { - c.getPackageManager(); - String apksign = "error getting package signature"; - - String version = "error getting version"; - try { - @SuppressLint("PackageManagerGetSignatures") - Signature raw = c.getPackageManager().getPackageInfo(c.getPackageName(), PackageManager.GET_SIGNATURES).signatures[0]; - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(raw.toByteArray())); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] der = cert.getEncoded(); - md.update(der); - byte[] digest = md.digest(); - - if (Arrays.equals(digest, officalkey)) - apksign = c.getString(R.string.official_build); - else if (Arrays.equals(digest, officaldebugkey)) - apksign = c.getString(R.string.debug_build); - else if (Arrays.equals(digest, amazonkey)) - apksign = "amazon version"; - else if (Arrays.equals(digest, fdroidkey)) - apksign = "F-Droid built and signed version"; - else - apksign = c.getString(R.string.built_by, cert.getSubjectX500Principal().getName()); - - PackageInfo packageinfo = c.getPackageManager().getPackageInfo(c.getPackageName(), 0); - version = packageinfo.versionName; - - } catch (NameNotFoundException | CertificateException | - NoSuchAlgorithmException ignored) { - } - - Object[] argsext = Arrays.copyOf(mArgs, mArgs.length); - argsext[argsext.length - 1] = apksign; - argsext[argsext.length - 2] = version; - - return c.getString(R.string.mobile_info, argsext); - - } - - public long getLogtime() { - return logtime; - } - - - public int getVerbosityLevel() { - if (mVerbosityLevel == -1) { - // Hack: - // For message not from OpenVPN, report the status level as log level - return mLevel.getInt(); - } - return mVerbosityLevel; - } - - public boolean verify() { - if (mLevel == null) - return false; - - if (mMessage == null && mRessourceId == 0) - return false; - - return true; - } - } - public interface LogListener { void newLog(LogItem logItem); } public interface StateListener { void updateState(String state, String logmessage, int localizedResId, ConnectionStatus level); + + void setConnectedVPN(String uuid); } public interface ByteCountListener { @@ -404,12 +231,20 @@ public class VpnStatus { public synchronized static void clearLog() { logbuffer.clear(); logInformation(); - mLogFileHandler.sendEmptyMessage(LogFileHandler.TRIM_LOG_FILE); + if (mLogFileHandler != null) + mLogFileHandler.sendEmptyMessage(LogFileHandler.TRIM_LOG_FILE); } private static void logInformation() { + String nativeAPI; + try { + nativeAPI = NativeUtils.getNativeAPI(); + } catch (UnsatisfiedLinkError ignore) { + nativeAPI = "error"; + } + logInfo(R.string.mobile_info, Build.MODEL, Build.BOARD, Build.BRAND, Build.VERSION.SDK_INT, - NativeUtils.getNativeAPI(), Build.VERSION.RELEASE, Build.ID, Build.FINGERPRINT, "", ""); + nativeAPI, Build.VERSION.RELEASE, Build.ID, Build.FINGERPRINT, "", ""); } public synchronized static void addLogListener(LogListener ll) { @@ -421,7 +256,8 @@ public class VpnStatus { } public synchronized static void addByteCountListener(ByteCountListener bcl) { - bcl.updateByteCount(mlastByteCount[0], mlastByteCount[1], mlastByteCount[2], mlastByteCount[3]); + TrafficHistory.LastDiff diff = trafficHistory.getLastDiff(null); + bcl.updateByteCount(diff.getIn(), diff.getOut(), diff.getDiffIn(),diff.getDiffOut()); byteCountListener.add(bcl); } @@ -525,7 +361,7 @@ public class VpnStatus { } - public static void updateStateString(String state, String msg) { + static void updateStateString(String state, String msg) { int rid = getLocalizedState(state); ConnectionStatus level = getLevel(state); updateStateString(state, msg, rid, level); @@ -549,7 +385,7 @@ public class VpnStatus { for (StateListener sl : stateListener) { sl.updateState(state, msg, resid, level); } - //newLogItem(new LogItem((LogLevel.DEBUG), String.format("New OpenVPN Status (%s->%s): %s",state,level.toString(),msg))); + newLogItem(new LogItem((LogLevel.DEBUG), String.format("New OpenVPN Status (%s->%s): %s",state,level.toString(),msg))); } public static void logInfo(String message) { @@ -568,7 +404,7 @@ public class VpnStatus { newLogItem(new LogItem(LogLevel.DEBUG, resourceId, args)); } - private static void newLogItem(LogItem logItem) { + static void newLogItem(LogItem logItem) { newLogItem(logItem, false); } @@ -578,18 +414,21 @@ public class VpnStatus { logbuffer.addFirst(logItem); } else { logbuffer.addLast(logItem); - Message m = mLogFileHandler.obtainMessage(LogFileHandler.LOG_MESSAGE, logItem); - mLogFileHandler.sendMessage(m); + if (mLogFileHandler != null) { + Message m = mLogFileHandler.obtainMessage(LogFileHandler.LOG_MESSAGE, logItem); + mLogFileHandler.sendMessage(m); + } } if (logbuffer.size() > MAXLOGENTRIES + MAXLOGENTRIES / 2) { while (logbuffer.size() > MAXLOGENTRIES) logbuffer.removeFirst(); - mLogFileHandler.sendMessage(mLogFileHandler.obtainMessage(LogFileHandler.TRIM_LOG_FILE)); + if (mLogFileHandler != null) + mLogFileHandler.sendMessage(mLogFileHandler.obtainMessage(LogFileHandler.TRIM_LOG_FILE)); } - if (BuildConfig.DEBUG && !cachedLine) - Log.d("OpenVPN", logItem.getString(null)); + //if (BuildConfig.DEBUG && !cachedLine && !BuildConfig.FLAVOR.equals("test")) + // Log.d("OpenVPN", logItem.getString(null)); for (LogListener ll : logListener) { @@ -627,17 +466,10 @@ public class VpnStatus { public static synchronized void updateByteCount(long in, long out) { - long lastIn = mlastByteCount[0]; - long lastOut = mlastByteCount[1]; - long diffIn = mlastByteCount[2] = Math.max(0, in - lastIn); - long diffOut = mlastByteCount[3] = Math.max(0, out - lastOut); - + TrafficHistory.LastDiff diff = trafficHistory.add(in, out); - mlastByteCount = new long[]{in, out, diffIn, diffOut}; for (ByteCountListener bcl : byteCountListener) { - bcl.updateByteCount(in, out, diffIn, diffOut); + bcl.updateByteCount(in, out, diff.getDiffIn(), diff.getDiffOut()); } } - - } |