summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2012-12-24 07:47:50 +0100
committerArne Schwabe <arne@rfc2549.org>2012-12-24 07:47:50 +0100
commit192410e3f1d5588712a85bbd7e9fd801dc5a0989 (patch)
treedd4340a12581a2ff6928973b61b7a47624ec3680
parent6023835ef31cd5ee5c54604140f9352939b477a7 (diff)
Make send mini dump work with non Gmail Mail app, make google sending better placed
-rw-r--r--AndroidManifest.xml5
-rw-r--r--openvpn/Android.mk2
-rw-r--r--openvpn/src/openvpn/breakpad.cpp29
-rw-r--r--openvpn/src/openvpn/breakpad.h13
-rw-r--r--openvpn/src/openvpn/error.c7
-rw-r--r--openvpn/src/openvpn/openvpn.c10
-rw-r--r--openvpn/src/openvpn/socket.c2
-rw-r--r--res/menu/logmenu.xml6
-rwxr-xr-xres/values/strings.xml3
-rw-r--r--src/de/blinkt/openvpn/FileProvider.java206
-rw-r--r--src/de/blinkt/openvpn/LogWindow.java70
-rw-r--r--src/de/blinkt/openvpn/MainActivity.java14
-rw-r--r--src/de/blinkt/openvpn/OpenVPN.java58
-rw-r--r--src/de/blinkt/openvpn/OpenVPNThread.java21
-rw-r--r--src/de/blinkt/openvpn/OpenVpnManagementThread.java10
-rw-r--r--src/de/blinkt/openvpn/SendDumpActivity.java60
16 files changed, 314 insertions, 202 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 8ccd1e9..564d439 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 6307e5e..c68bccc 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 0000000..cfcc10a
--- /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 0000000..84df62a
--- /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 ebe9a52..98611a1 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 4bae527..a177d9e 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 29a15a6..9a33197 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 ec2997b..bb810df 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 eea81d8..3613c7d 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 1147ccf..e86b544 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 3c0f724..790e143 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 9b32981..32cf575 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 4862386..0ae681b 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 13b8688..7d58552 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 d15e6a3..9926ba1 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 0000000..8a09b53
--- /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;
+ }
+}