summaryrefslogtreecommitdiff
path: root/app/src/main/java/de/blinkt/openvpn/core/OpenVPNStatusService.java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/de/blinkt/openvpn/core/OpenVPNStatusService.java')
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVPNStatusService.java232
1 files changed, 232 insertions, 0 deletions
diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNStatusService.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNStatusService.java
new file mode 100644
index 00000000..6df1379a
--- /dev/null
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNStatusService.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2012-2016 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
+package de.blinkt.openvpn.core;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.support.annotation.Nullable;
+import android.util.Pair;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+
+/**
+ * Created by arne on 08.11.16.
+ */
+
+public class OpenVPNStatusService extends Service implements VpnStatus.LogListener, VpnStatus.ByteCountListener, VpnStatus.StateListener {
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+
+ static final RemoteCallbackList<IStatusCallbacks> mCallbacks =
+ new RemoteCallbackList<>();
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ VpnStatus.addLogListener(this);
+ VpnStatus.addByteCountListener(this);
+ VpnStatus.addStateListener(this);
+ mHandler.setService(this);
+
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+
+ VpnStatus.removeLogListener(this);
+ VpnStatus.removeByteCountListener(this);
+ VpnStatus.removeStateListener(this);
+ mCallbacks.kill();
+
+ }
+
+ private static final IServiceStatus.Stub mBinder = new IServiceStatus.Stub() {
+
+ @Override
+ public ParcelFileDescriptor registerStatusCallback(IStatusCallbacks cb) throws RemoteException {
+ final LogItem[] logbuffer = VpnStatus.getlogbuffer();
+ if (mLastUpdateMessage != null)
+ sendUpdate(cb, mLastUpdateMessage);
+
+ mCallbacks.register(cb);
+ try {
+ final ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
+ new Thread("pushLogs") {
+ @Override
+ public void run() {
+ DataOutputStream fd = new DataOutputStream(new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]));
+ try {
+ synchronized (VpnStatus.readFileLock) {
+ if (!VpnStatus.readFileLog) {
+ VpnStatus.readFileLock.wait();
+ }
+ }
+ } catch (InterruptedException e) {
+ VpnStatus.logException(e);
+ }
+ try {
+
+ for (LogItem logItem : logbuffer) {
+ byte[] bytes = logItem.getMarschaledBytes();
+ fd.writeShort(bytes.length);
+ fd.write(bytes);
+ }
+ // Mark end
+ fd.writeShort(0x7fff);
+ fd.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+ }.start();
+ return pipe[0];
+ } catch (IOException e) {
+ e.printStackTrace();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
+ throw new RemoteException(e.getMessage());
+ }
+ return null;
+ }
+ }
+
+ @Override
+ public void unregisterStatusCallback(IStatusCallbacks cb) throws RemoteException {
+ mCallbacks.unregister(cb);
+ }
+
+ @Override
+ public String getLastConnectedVPN() throws RemoteException {
+ return VpnStatus.getLastConnectedVPNProfile();
+ }
+
+ @Override
+ public void setCachedPassword(String uuid, int type, String password) {
+ PasswordCache.setCachedPassword(uuid, type, password);
+ }
+
+ @Override
+ public TrafficHistory getTrafficHistory() throws RemoteException {
+ return VpnStatus.trafficHistory;
+ }
+
+ };
+
+ @Override
+ public void newLog(LogItem logItem) {
+ Message msg = mHandler.obtainMessage(SEND_NEW_LOGITEM, logItem);
+ msg.sendToTarget();
+ }
+
+ @Override
+ public void updateByteCount(long in, long out, long diffIn, long diffOut) {
+ Message msg = mHandler.obtainMessage(SEND_NEW_BYTECOUNT, Pair.create(in, out));
+ msg.sendToTarget();
+ }
+
+ static UpdateMessage mLastUpdateMessage;
+
+ static class UpdateMessage {
+ public String state;
+ public String logmessage;
+ public ConnectionStatus level;
+ int resId;
+
+ UpdateMessage(String state, String logmessage, int resId, ConnectionStatus level) {
+ this.state = state;
+ this.resId = resId;
+ this.logmessage = logmessage;
+ this.level = level;
+ }
+ }
+
+
+ @Override
+ public void updateState(String state, String logmessage, int localizedResId, ConnectionStatus level) {
+
+ mLastUpdateMessage = new UpdateMessage(state, logmessage, localizedResId, level);
+ Message msg = mHandler.obtainMessage(SEND_NEW_STATE, mLastUpdateMessage);
+ msg.sendToTarget();
+ }
+
+ @Override
+ public void setConnectedVPN(String uuid) {
+ Message msg = mHandler.obtainMessage(SEND_NEW_CONNECTED_VPN, uuid);
+ msg.sendToTarget();
+ }
+
+ private static final OpenVPNStatusHandler mHandler = new OpenVPNStatusHandler();
+
+ private static final int SEND_NEW_LOGITEM = 100;
+ private static final int SEND_NEW_STATE = 101;
+ private static final int SEND_NEW_BYTECOUNT = 102;
+ private static final int SEND_NEW_CONNECTED_VPN = 103;
+
+ private static class OpenVPNStatusHandler extends Handler {
+ WeakReference<OpenVPNStatusService> service = null;
+
+ private void setService(OpenVPNStatusService statusService) {
+ service = new WeakReference<>(statusService);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+
+ RemoteCallbackList<IStatusCallbacks> callbacks;
+ if (service == null || service.get() == null)
+ return;
+ callbacks = service.get().mCallbacks;
+ // Broadcast to all clients the new value.
+ final int N = callbacks.beginBroadcast();
+ for (int i = 0; i < N; i++) {
+
+ try {
+ IStatusCallbacks broadcastItem = callbacks.getBroadcastItem(i);
+
+ switch (msg.what) {
+ case SEND_NEW_LOGITEM:
+ broadcastItem.newLogItem((LogItem) msg.obj);
+ break;
+ case SEND_NEW_BYTECOUNT:
+ Pair<Long, Long> inout = (Pair<Long, Long>) msg.obj;
+ broadcastItem.updateByteCount(inout.first, inout.second);
+ break;
+ case SEND_NEW_STATE:
+ sendUpdate(broadcastItem, (UpdateMessage) msg.obj);
+ break;
+
+ case SEND_NEW_CONNECTED_VPN:
+ broadcastItem.connectedVPN((String) msg.obj);
+ break;
+ }
+ } catch (RemoteException e) {
+ // The RemoteCallbackList will take care of removing
+ // the dead object for us.
+ }
+ }
+ callbacks.finishBroadcast();
+ }
+ }
+
+ private static void sendUpdate(IStatusCallbacks broadcastItem,
+ UpdateMessage um) throws RemoteException {
+ broadcastItem.updateStateString(um.state, um.logmessage, um.resId, um.level);
+ }
+} \ No newline at end of file