diff options
author | Arne Schwabe <arne@rfc2549.org> | 2012-12-24 07:47:50 +0100 |
---|---|---|
committer | Arne Schwabe <arne@rfc2549.org> | 2012-12-24 07:47:50 +0100 |
commit | 192410e3f1d5588712a85bbd7e9fd801dc5a0989 (patch) | |
tree | dd4340a12581a2ff6928973b61b7a47624ec3680 | |
parent | 6023835ef31cd5ee5c54604140f9352939b477a7 (diff) |
Make send mini dump work with non Gmail Mail app, make google sending better placed
-rw-r--r-- | AndroidManifest.xml | 5 | ||||
-rw-r--r-- | openvpn/Android.mk | 2 | ||||
-rw-r--r-- | openvpn/src/openvpn/breakpad.cpp | 29 | ||||
-rw-r--r-- | openvpn/src/openvpn/breakpad.h | 13 | ||||
-rw-r--r-- | openvpn/src/openvpn/error.c | 7 | ||||
-rw-r--r-- | openvpn/src/openvpn/openvpn.c | 10 | ||||
-rw-r--r-- | openvpn/src/openvpn/socket.c | 2 | ||||
-rw-r--r-- | res/menu/logmenu.xml | 6 | ||||
-rwxr-xr-x | res/values/strings.xml | 3 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/FileProvider.java | 206 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/LogWindow.java | 70 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/MainActivity.java | 14 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVPN.java | 58 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVPNThread.java | 21 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/OpenVpnManagementThread.java | 10 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/SendDumpActivity.java | 60 |
16 files changed, 314 insertions, 202 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 8ccd1e96..564d4396 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -43,6 +43,7 @@ <activity android:name=".LogWindow" android:label="@string/openvpn_log" /> + <activity android:name=".SendDumpActivity" /> <activity android:name=".FileSelect" /> <activity android:name=".MainActivity" > <intent-filter> @@ -121,8 +122,8 @@ <provider android:name=".FileProvider" android:authorities="de.blinkt.openvpn.FileProvider" - android:grantUriPermissions="true" - android:exported="true" /> + android:exported="true" + android:grantUriPermissions="true" /> </application> </manifest>
\ No newline at end of file diff --git a/openvpn/Android.mk b/openvpn/Android.mk index 6307e5e0..c68bcccf 100644 --- a/openvpn/Android.mk +++ b/openvpn/Android.mk @@ -91,7 +91,7 @@ LOCAL_SRC_FILES:= \ src/openvpn/status.c \ src/openvpn/tun.c ifneq ($(TARGET_ARCH),mips) -LOCAL_SRC_FILES+=../jni/icsandroid.cpp +LOCAL_SRC_FILES+=src/openvpn/breakpad.cpp endif diff --git a/openvpn/src/openvpn/breakpad.cpp b/openvpn/src/openvpn/breakpad.cpp new file mode 100644 index 00000000..cfcc10a8 --- /dev/null +++ b/openvpn/src/openvpn/breakpad.cpp @@ -0,0 +1,29 @@ + +#include "breakpad.h" +#include "client/linux/handler/exception_handler.h" + + +static +bool DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, + void* context, + bool succeeded) { + printf("Dump path: %s\n", descriptor.path()); + fflush(stdout); + fflush(stderr); + return succeeded; +} + +static google_breakpad::MinidumpDescriptor* desc; +static google_breakpad::ExceptionHandler* eh; + +void breakpad_setup(void) +{ + printf("Initializing Google Breakpad!\n"); + desc = new google_breakpad::MinidumpDescriptor("/data/data/de.blinkt.openvpn/cache"); + eh = new google_breakpad::ExceptionHandler(*desc, NULL, DumpCallback, NULL, true,-1); +} + +void breakpad_dodump(void) +{ + eh->WriteMinidump(); +} diff --git a/openvpn/src/openvpn/breakpad.h b/openvpn/src/openvpn/breakpad.h new file mode 100644 index 00000000..84df62ab --- /dev/null +++ b/openvpn/src/openvpn/breakpad.h @@ -0,0 +1,13 @@ +#ifndef BUFFER_H +#define BUFFER_H + +#ifdef __cplusplus +extern "C" { +#endif + void breakpad_setup(void); + void breakpad_dodump(void); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/openvpn/src/openvpn/error.c b/openvpn/src/openvpn/error.c index ebe9a52d..98611a1b 100644 --- a/openvpn/src/openvpn/error.c +++ b/openvpn/src/openvpn/error.c @@ -57,6 +57,10 @@ #endif #endif +#ifdef GOOGLE_BREAKPAD +#include "breakpad.h" +#endif + /* Globals */ unsigned int x_debug_level; /* GLOBAL */ @@ -399,6 +403,9 @@ dont_mute (unsigned int flags) void assert_failed (const char *filename, int line) { +#ifdef GOOGLE_BREAKPAD + breakpad_dodump(); +#endif msg (M_FATAL, "Assertion failed at %s:%d", filename, line); } diff --git a/openvpn/src/openvpn/openvpn.c b/openvpn/src/openvpn/openvpn.c index 4bae5274..a177d9e8 100644 --- a/openvpn/src/openvpn/openvpn.c +++ b/openvpn/src/openvpn/openvpn.c @@ -41,6 +41,10 @@ #define P2P_CHECK_SIG() EVENT_LOOP_CHECK_SIGNAL (c, process_signal_p2p, c); +#ifdef GOOGLE_BREAKPAD +#include "breakpad.h" +#endif + static bool process_signal_p2p (struct context *c) { @@ -321,12 +325,10 @@ wmain (int argc, wchar_t *wargv[]) { #else int main (int argc, char *argv[]) { -#ifdef TARGET_ANDROID #ifdef GOOGLE_BREAKPAD -#include "../jni/icsandroid.h" - setup_breakpad(); -#endif + breakpad_setup(); #endif + return openvpn_main(argc, argv); } #endif diff --git a/openvpn/src/openvpn/socket.c b/openvpn/src/openvpn/socket.c index 29a15a63..9a33197c 100644 --- a/openvpn/src/openvpn/socket.c +++ b/openvpn/src/openvpn/socket.c @@ -1255,7 +1255,7 @@ resolve_remote (struct link_socket *sock, if (remote_dynamic) *remote_dynamic = NULL; } - else + /* else, quick hack to fix persistent-remote ....*/ { CLEAR (sock->info.lsa->actual); if(sock->info.lsa->current_remote) diff --git a/res/menu/logmenu.xml b/res/menu/logmenu.xml index ec2997b0..bb810df0 100644 --- a/res/menu/logmenu.xml +++ b/res/menu/logmenu.xml @@ -1,12 +1,6 @@ <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:id="@+id/minidump"
- android:icon="@android:drawable/ic_menu_upload"
- android:showAsAction="ifRoom|withText"
- android:title="Send Minidump to developer"
- android:titleCondensed="Send Minidump"/>
- <item
android:id="@+id/clearlog"
android:icon="@drawable/ic_menu_trash_holo_light"
android:showAsAction="ifRoom|withText"
diff --git a/res/values/strings.xml b/res/values/strings.xml index eea81d8b..3613c7d1 100755 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -236,5 +236,8 @@ <string name="reconnection_settings">Reconnection settings</string> <string name="connectretrymessage">Number of seconds to wait between connection attempts.</string> <string name="connectretrywait">Seconds between connections</string> + <string name="minidump_generated">OpenVPN crashed unexpectedly. Please consider using the send Minidump option in the main menu</string> + <string name="send_minidump">Send Minidump to developer</string> + <string name="send_minidump_summary">Send debugging information about last crash to developer</string> </resources> diff --git a/src/de/blinkt/openvpn/FileProvider.java b/src/de/blinkt/openvpn/FileProvider.java index 1147ccf0..e86b544f 100644 --- a/src/de/blinkt/openvpn/FileProvider.java +++ b/src/de/blinkt/openvpn/FileProvider.java @@ -24,13 +24,15 @@ import java.io.IOException; import java.io.InputStream; import android.content.ContentProvider; -import android.content.ContentValues; import android.content.ContentProvider.PipeDataWriter; +import android.content.ContentValues; import android.content.res.AssetFileDescriptor; import android.database.Cursor; +import android.database.MatrixCursor; import android.net.Uri; import android.os.Bundle; import android.os.ParcelFileDescriptor; +import android.provider.OpenableColumns; import android.util.Log; /** @@ -38,92 +40,118 @@ import android.util.Log; * our .apk. */ public class FileProvider extends ContentProvider - implements PipeDataWriter<InputStream> { - @Override - public boolean onCreate() { - return true; - } - - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - // Don't support queries. - return null; - } - - @Override - public Uri insert(Uri uri, ContentValues values) { - // Don't support inserts. - return null; - } - - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - // Don't support deletes. - return 0; - } - - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - // Don't support updates. - return 0; - } - - @Override - public String getType(Uri uri) { - // For this sample, assume all files are .apks. - return "application/octet-stream"; - } - - @Override - public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { - // Try to open an asset with the given name. - String path = uri.getPath(); - if(path.startsWith("/")) - path = path.replaceFirst("/", ""); - - // I think this already random enough, no need for magic secure cookies - // 1f9563a4-a1f5-2165-255f2219-111823ef.dmp - if (!path.matches("^[0-9a-z-.]*$")) - throw new FileNotFoundException("url not in expect format " + uri); - - try { - - File cachedir = getContext().getCacheDir(); - File dumpfile = new File(cachedir,path); - InputStream is = new FileInputStream(dumpfile); - // Start a new thread that pipes the stream data back to the caller. - return new AssetFileDescriptor( - openPipeHelper(uri, null, null, is, this), 0, - dumpfile.length()); - } catch (IOException e) { - FileNotFoundException fnf = new FileNotFoundException("Unable to open minidump " + uri); - throw fnf; - } - } - - @Override - public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType, - Bundle opts, InputStream args) { - // Transfer data from the asset to the pipe the client is reading. - byte[] buffer = new byte[8192]; - int n; - FileOutputStream fout = new FileOutputStream(output.getFileDescriptor()); - try { - while ((n=args.read(buffer)) >= 0) { - fout.write(buffer, 0, n); - } - } catch (IOException e) { - Log.i("OpenVPNFileProvider", "Failed transferring", e); - } finally { - try { - args.close(); - } catch (IOException e) { - } - try { - fout.close(); - } catch (IOException e) { - } - } - } +implements PipeDataWriter<InputStream> { + @Override + public boolean onCreate() { + return true; + } + + @Override + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, + String sortOrder) { + try { + File dumpfile = getFileFromURI(uri); + + + MatrixCursor c = new MatrixCursor(projection); + + Object[] row = new Object[projection.length]; + int i=0; + for (String r:projection) { + if(r.equals(OpenableColumns.SIZE)) + row[i] = dumpfile.length(); + if(r.equals(OpenableColumns.DISPLAY_NAME)) + row[i] = dumpfile.getName(); + i++; + } + c.addRow(row); + return c; + } catch (FileNotFoundException e) { + e.printStackTrace(); + return null; + } + + + } + + @Override + public Uri insert(Uri uri, ContentValues values) { + // Don't support inserts. + return null; + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + // Don't support deletes. + return 0; + } + + @Override + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + // Don't support updates. + return 0; + } + + @Override + public String getType(Uri uri) { + // For this sample, assume all files are .apks. + return "application/octet-stream"; + } + + @Override + public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { + File dumpfile = getFileFromURI(uri); + + try { + + InputStream is = new FileInputStream(dumpfile); + // Start a new thread that pipes the stream data back to the caller. + return new AssetFileDescriptor( + openPipeHelper(uri, null, null, is, this), 0, + dumpfile.length()); + } catch (IOException e) { + FileNotFoundException fnf = new FileNotFoundException("Unable to open minidump " + uri); + throw fnf; + } + } + + private File getFileFromURI(Uri uri) throws FileNotFoundException { + // Try to open an asset with the given name. + String path = uri.getPath(); + if(path.startsWith("/")) + path = path.replaceFirst("/", ""); + + // I think this already random enough, no need for magic secure cookies + // 1f9563a4-a1f5-2165-255f2219-111823ef.dmp + if (!path.matches("^[0-9a-z-.]*(dmp|dmp.log)$")) + throw new FileNotFoundException("url not in expect format " + uri); + File cachedir = getContext().getCacheDir(); + File dumpfile = new File(cachedir,path); + return dumpfile; + } + + @Override + public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType, + Bundle opts, InputStream args) { + // Transfer data from the asset to the pipe the client is reading. + byte[] buffer = new byte[8192]; + int n; + FileOutputStream fout = new FileOutputStream(output.getFileDescriptor()); + try { + while ((n=args.read(buffer)) >= 0) { + fout.write(buffer, 0, n); + } + } catch (IOException e) { + Log.i("OpenVPNFileProvider", "Failed transferring", e); + } finally { + try { + args.close(); + } catch (IOException e) { + } + try { + fout.close(); + } catch (IOException e) { + } + } + } } diff --git a/src/de/blinkt/openvpn/LogWindow.java b/src/de/blinkt/openvpn/LogWindow.java index 3c0f7246..790e143a 100644 --- a/src/de/blinkt/openvpn/LogWindow.java +++ b/src/de/blinkt/openvpn/LogWindow.java @@ -1,9 +1,5 @@ package de.blinkt.openvpn; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; import java.util.Vector; import android.app.AlertDialog; @@ -16,7 +12,6 @@ import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.database.DataSetObserver; -import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Handler.Callback; @@ -227,8 +222,6 @@ public class LogWindow extends ListActivity implements StateListener { } else if(item.getItemId()==R.id.info) { if(mBconfig==null) OpenVPN.triggerLogBuilderConfig(); - } else if(item.getItemId()==R.id.minidump) { - emailMiniDumps(); } else if(item.getItemId()==R.id.send) { ladapter.shareLog(); @@ -258,72 +251,9 @@ public class LogWindow extends ListActivity implements StateListener { public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.logmenu, menu); - - - - if(getLastestDump()==null) - menu.removeItem(R.id.minidump); - return true; } - private File getLastestDump() { - long newestDumpTime=0; - File newestDumpFile=null; - - for(File f:getCacheDir().listFiles()) { - if(!f.getName().endsWith(".dmp")) - continue; - - if (newestDumpTime < f.lastModified()) { - newestDumpTime = f.lastModified(); - newestDumpFile=f; - } - } - return newestDumpFile; - } - - - public void emailMiniDumps() - { - //need to "send multiple" to get more than one attachment - final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND_MULTIPLE); - emailIntent.setType("*/*"); - emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, - new String[]{"Arne Schwabe <arne@rfc2549.org>"}); - emailIntent.putExtra(Intent.EXTRA_SUBJECT, "OpenVPN Minidump"); - - - ArrayList<CharSequence> textarraylist = new ArrayList<CharSequence>(); - textarraylist.add("Please describe the issue you have experienced"); - emailIntent.putExtra(Intent.EXTRA_TEXT, textarraylist); - - - ArrayList<Uri> uris = new ArrayList<Uri>(); - - File ldump = getLastestDump(); - if(ldump==null) { - OpenVPN.logError("No Minidump found!"); - } - - uris.add(Uri.parse("content://de.blinkt.openvpn.FileProvider/" + ldump.getName())); - uris.add(Uri.parse("content://de.blinkt.openvpn.FileProvider/openvpn.log")); - - - try { - FileWriter logout = new FileWriter(new File(getCacheDir(),"openvpn.log")); - logout.write(ladapter.getLogStr()); - logout.close(); - - } catch (IOException e1) { - OpenVPN.logError("Error writing log: " + e1.getLocalizedMessage()); - } - - //emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); - startActivity(emailIntent); - } - @Override protected void onResume() { diff --git a/src/de/blinkt/openvpn/MainActivity.java b/src/de/blinkt/openvpn/MainActivity.java index 9b329817..32cf575b 100644 --- a/src/de/blinkt/openvpn/MainActivity.java +++ b/src/de/blinkt/openvpn/MainActivity.java @@ -1,8 +1,11 @@ package de.blinkt.openvpn; +import java.io.File; +import java.util.ArrayList; import java.util.List; import android.content.Intent; +import android.net.Uri; import android.preference.PreferenceActivity; public class MainActivity extends PreferenceActivity { @@ -19,6 +22,15 @@ public class MainActivity extends PreferenceActivity { translation.summary = translatedby; target.add(translation); } + + if(SendDumpActivity.getLastestDump(this)!=null) { + Header sendDump = new Header(); + sendDump.titleRes = R.string.send_minidump; + sendDump.summaryRes = R.string.send_minidump_summary; + sendDump.intent = new Intent(this,SendDumpActivity.class); + target.add(sendDump); + } + } @Override @@ -29,4 +41,6 @@ public class MainActivity extends PreferenceActivity { } + + } diff --git a/src/de/blinkt/openvpn/OpenVPN.java b/src/de/blinkt/openvpn/OpenVPN.java index 48623865..0ae681bc 100644 --- a/src/de/blinkt/openvpn/OpenVPN.java +++ b/src/de/blinkt/openvpn/OpenVPN.java @@ -7,10 +7,10 @@ import android.content.Context; import android.os.Build; public class OpenVPN { - + public static LinkedList<LogItem> logbuffer; - + private static Vector<LogListener> logListener; private static Vector<StateListener> stateListener; private static String[] mBconfig; @@ -18,14 +18,14 @@ public class OpenVPN { private static String mLaststatemsg; private static String mLaststate; - + static { logbuffer = new LinkedList<LogItem>(); logListener = new Vector<OpenVPN.LogListener>(); stateListener = new Vector<OpenVPN.StateListener>(); logInformation(); } - + static class LogItem { public static final int ERROR = 1; public static final int INFO = 2; @@ -36,20 +36,20 @@ public class OpenVPN { private int mRessourceId; // Default log priority int mLevel = INFO; - + public LogItem(int ressourceId, Object[] args) { - mRessourceId = ressourceId; - mArgs = args; + mRessourceId = ressourceId; + mArgs = args; } - + public LogItem(int loglevel,int ressourceId, Object[] args) { - mRessourceId = ressourceId; - mArgs = args; - mLevel = loglevel; - } + mRessourceId = ressourceId; + mArgs = args; + mLevel = loglevel; + } + - public LogItem(String message) { mMessage = message; } @@ -70,28 +70,32 @@ public class OpenVPN { if(mMessage !=null) { return mMessage; } else { - if(mArgs == null) - return c.getString(mRessourceId); - else - return c.getString(mRessourceId,mArgs); + if(c!=null) { + if(mArgs == null) + return c.getString(mRessourceId); + else + return c.getString(mRessourceId,mArgs); + } else { + return String.format("Log (no context) resid %d", mRessourceId); + } } } } - + private static final int MAXLOGENTRIES = 200; public static final String MANAGMENT_PREFIX = "M:"; - + public interface LogListener { void newLog(LogItem logItem); } - + public interface StateListener { void updateState(String state, String logmessage); } @@ -108,7 +112,7 @@ public class OpenVPN { } private static void logInformation() { - + logInfo(R.string.mobile_info,Build.MODEL, Build.BOARD,Build.BRAND,Build.VERSION.SDK_INT); } @@ -120,7 +124,7 @@ public class OpenVPN { logListener.remove(ll); } - + synchronized static void addStateListener(StateListener sl){ stateListener.add(sl); if(mLaststate!=null) @@ -156,7 +160,7 @@ public class OpenVPN { public synchronized static void updateStateString(String state, String msg) { mLaststate= state; mLaststatemsg = msg; - + for (StateListener sl : stateListener) { sl.updateState(state,msg); } @@ -174,7 +178,7 @@ public class OpenVPN { logbuffer.addLast(logItem); if(logbuffer.size()>MAXLOGENTRIES) logbuffer.removeFirst(); - + for (LogListener ll : logListener) { ll.newLog(logItem); } @@ -182,7 +186,7 @@ public class OpenVPN { public static void logError(String msg) { newlogItem(new LogItem(LogItem.ERROR, msg)); - + } public static void logError(int ressourceId) { @@ -191,6 +195,6 @@ public class OpenVPN { public static void logError(int ressourceId, Object... args) { newlogItem(new LogItem(LogItem.ERROR, ressourceId,args)); } - - + + } diff --git a/src/de/blinkt/openvpn/OpenVPNThread.java b/src/de/blinkt/openvpn/OpenVPNThread.java index 13b8688b..7d58552a 100644 --- a/src/de/blinkt/openvpn/OpenVPNThread.java +++ b/src/de/blinkt/openvpn/OpenVPNThread.java @@ -1,19 +1,24 @@ package de.blinkt.openvpn;
import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.LinkedList;
import android.util.Log;
+import de.blinkt.openvpn.OpenVPN.LogItem;
public class OpenVPNThread implements Runnable {
+ private static final String DUMP_PATH_STRING = "Dump path: ";
private static final String TAG = "OpenVPN";
private String[] mArgv;
private Process mProcess;
private String mNativeDir;
private OpenVpnService mService;
+ private String mDumpPath;
public OpenVPNThread(OpenVpnService service,String[] argv, String nativelibdir)
{
@@ -49,7 +54,18 @@ public class OpenVPNThread implements Runnable { OpenVPN.logError("Process exited with exit value " + exitvalue);
OpenVPN.updateStateString("NOPROCESS","No process running.");
-
+ if(mDumpPath!=null) {
+ try {
+ BufferedWriter logout = new BufferedWriter(new FileWriter(mDumpPath + ".log"));
+ for(LogItem li :OpenVPN.getlogbuffer()){
+ logout.write(li.getString(null) + "\n");
+ }
+ logout.close();
+ OpenVPN.logError(R.string.minidump_generated);
+ } catch (IOException e) {
+ OpenVPN.logError("Writing minidump log: " +e.getLocalizedMessage());
+ }
+ }
mService.processDied();
Log.i(TAG, "Exiting");
@@ -89,6 +105,9 @@ public class OpenVPNThread implements Runnable { while(true) {
String logline = br.readLine();
+ if (logline.startsWith(DUMP_PATH_STRING))
+ mDumpPath = logline.substring(DUMP_PATH_STRING.length());
+
if(logline==null) {
return;
}
diff --git a/src/de/blinkt/openvpn/OpenVpnManagementThread.java b/src/de/blinkt/openvpn/OpenVpnManagementThread.java index d15e6a33..9926ba13 100644 --- a/src/de/blinkt/openvpn/OpenVpnManagementThread.java +++ b/src/de/blinkt/openvpn/OpenVpnManagementThread.java @@ -39,7 +39,8 @@ public class OpenVpnManagementThread implements Runnable { private long mLastOut=0;
private LocalServerSocket mServerSocket;
private boolean mReleaseHold=true;
- private boolean mWaitingForRelease=false;
+ private boolean mWaitingForRelease=false;
+ private long mLastHoldRelease=0;
private static Vector<OpenVpnManagementThread> active=new Vector<OpenVpnManagementThread>();
@@ -223,8 +224,15 @@ public class OpenVpnManagementThread implements Runnable { }
}
private void releaseHoldCmd() {
+ if ((System.currentTimeMillis()- mLastHoldRelease) < 5000) {
+ try {
+ Thread.sleep(3000);
+ } catch (InterruptedException e) {}
+
+ }
mWaitingForRelease=false;
mReleaseHold=true;
+ mLastHoldRelease = System.currentTimeMillis();
managmentCommand("hold release\n");
managmentCommand("bytecount " + mBytecountinterval + "\n");
managmentCommand("state on\n");
diff --git a/src/de/blinkt/openvpn/SendDumpActivity.java b/src/de/blinkt/openvpn/SendDumpActivity.java new file mode 100644 index 00000000..8a09b535 --- /dev/null +++ b/src/de/blinkt/openvpn/SendDumpActivity.java @@ -0,0 +1,60 @@ +package de.blinkt.openvpn; + +import java.io.File; +import java.util.ArrayList; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; + +public class SendDumpActivity extends Activity { + + protected void onStart() { + super.onStart(); + emailMiniDumps(); + finish(); + }; + + public void emailMiniDumps() + { + //need to "send multiple" to get more than one attachment + final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND_MULTIPLE); + emailIntent.setType("*/*"); + emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, + new String[]{"Arne Schwabe <arne@rfc2549.org>"}); + emailIntent.putExtra(Intent.EXTRA_SUBJECT, "OpenVPN Minidump"); + + emailIntent.putExtra(Intent.EXTRA_TEXT, "Please describe the issue you have experienced"); + + ArrayList<Uri> uris = new ArrayList<Uri>(); + + File ldump = getLastestDump(this); + if(ldump==null) { + OpenVPN.logError("No Minidump found!"); + } + + uris.add(Uri.parse("content://de.blinkt.openvpn.FileProvider/" + ldump.getName())); + uris.add(Uri.parse("content://de.blinkt.openvpn.FileProvider/" + ldump.getName() + ".log")); + + emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); + startActivity(emailIntent); + } + + static public File getLastestDump(Context c) { + long newestDumpTime=0; + File newestDumpFile=null; + + for(File f:c.getCacheDir().listFiles()) { + if(!f.getName().endsWith(".dmp")) + continue; + + if (newestDumpTime < f.lastModified()) { + newestDumpTime = f.lastModified(); + newestDumpFile=f; + } + } + return newestDumpFile; + } +} |