Add stats in the intent-based API

This commit is contained in:
emanuele-f 2022-05-27 12:40:52 +02:00
parent 036ec19f5d
commit c32907d101
8 changed files with 51 additions and 20 deletions

View File

@ -67,7 +67,7 @@ import com.emanuelef.remote_capture.model.ConnectionUpdate;
import com.emanuelef.remote_capture.model.FilterDescriptor;
import com.emanuelef.remote_capture.model.MatchList;
import com.emanuelef.remote_capture.model.Prefs;
import com.emanuelef.remote_capture.model.VPNStats;
import com.emanuelef.remote_capture.model.CaptureStats;
import com.emanuelef.remote_capture.pcap_dump.FileDumper;
import com.emanuelef.remote_capture.pcap_dump.HTTPServer;
import com.emanuelef.remote_capture.interfaces.PcapDumper;
@ -134,6 +134,7 @@ public class CaptureService extends VpnService implements Runnable {
private String mSocks5Address;
private int mSocks5Port;
private String mSocks5Auth;
private CaptureStats mLastStats;
/* The maximum connections to log into the ConnectionsRegister. Older connections are dropped.
* Max estimated memory usage: less than 4 MB (+8 MB with payload mode minimal). */
@ -873,7 +874,7 @@ public class CaptureService extends VpnService implements Runnable {
// Notify
mHandler.post(() -> {
sendServiceStatus(SERVICE_STATUS_STOPPED);
CaptureCtrl.notifyCaptureStopped(this);
CaptureCtrl.notifyCaptureStopped(this, mLastStats);
});
mCaptureThread = null;
@ -1015,7 +1016,7 @@ public class CaptureService extends VpnService implements Runnable {
// from NetGuard
@TargetApi(Build.VERSION_CODES.Q)
public int getUidQ(int version, int protocol, String saddr, int sport, String daddr, int dport) {
public int getUidQ(int protocol, String saddr, int sport, String daddr, int dport) {
if (protocol != 6 /* TCP */ && protocol != 17 /* UDP */)
return Utils.UID_UNKNOWN;
@ -1044,8 +1045,9 @@ public class CaptureService extends VpnService implements Runnable {
}
}
public void sendStatsDump(VPNStats stats) {
public void sendStatsDump(CaptureStats stats) {
//Log.d(TAG, "sendStatsDump");
mLastStats = stats;
Bundle bundle = new Bundle();
bundle.putSerializable("value", stats);
@ -1160,6 +1162,10 @@ public class CaptureService extends VpnService implements Runnable {
nativeSetFirewallEnabled(enabled);
}
public static CaptureStats getStats() {
return((INSTANCE != null) ? INSTANCE.mLastStats : null);
}
private static native void runPacketLoop(int fd, CaptureService vpn, int sdk);
private static native void stopPacketLoop();
private static native int getFdSetSize();

View File

@ -51,6 +51,7 @@ import com.emanuelef.remote_capture.Utils;
import com.emanuelef.remote_capture.model.AppDescriptor;
import com.emanuelef.remote_capture.model.CaptureSettings;
import com.emanuelef.remote_capture.model.CtrlPermissions;
import com.emanuelef.remote_capture.model.CaptureStats;
public class CaptureCtrl extends AppCompatActivity {
public static final String ACTION_START = "start";
@ -204,12 +205,20 @@ public class CaptureCtrl extends AppCompatActivity {
CaptureService.stopService();
mStarterApp = null;
CaptureStats stats = CaptureService.getStats();
if(stats != null)
putStats(res, stats);
} else if(action.equals(ACTION_STATUS)) {
Log.d(TAG, "Returning status");
res.putExtra("running", CaptureService.isServiceActive());
res.putExtra("version_name", BuildConfig.VERSION_NAME);
res.putExtra("version_code", BuildConfig.VERSION_CODE);
CaptureStats stats = CaptureService.getStats();
if(stats != null)
putStats(res, stats);
} else {
Log.e(TAG, "unknown action: " + action);
abort();
@ -220,12 +229,14 @@ public class CaptureCtrl extends AppCompatActivity {
finish();
}
public static void notifyCaptureStopped(Context ctx) {
public static void notifyCaptureStopped(Context ctx, CaptureStats stats) {
if((mStarterApp != null) && (mReceiverClass != null)) {
Log.d(TAG, "Notifying receiver");
Intent intent = new Intent(ACTION_NOTIFY_STATUS);
intent.putExtra("running", false);
if(stats != null)
putStats(intent, stats);
intent.setComponent(new ComponentName(mStarterApp.getPackageName(), mReceiverClass));
try {
@ -238,4 +249,13 @@ public class CaptureCtrl extends AppCompatActivity {
mStarterApp = null;
mReceiverClass = null;
}
private static void putStats(Intent intent, CaptureStats stats) {
intent.putExtra("bytes_sent", stats.bytes_sent);
intent.putExtra("bytes_rcvd", stats.bytes_rcvd);
intent.putExtra("bytes_dumped", stats.pcap_dump_size);
intent.putExtra("pkts_sent", stats.pkts_sent);
intent.putExtra("pkts_rcvd", stats.pkts_rcvd);
intent.putExtra("pkts_dropped", stats.pkts_dropped);
}
}

View File

@ -38,7 +38,7 @@ import android.widget.TextView;
import com.emanuelef.remote_capture.CaptureService;
import com.emanuelef.remote_capture.R;
import com.emanuelef.remote_capture.Utils;
import com.emanuelef.remote_capture.model.VPNStats;
import com.emanuelef.remote_capture.model.CaptureStats;
public class StatsActivity extends BaseActivity {
private BroadcastReceiver mReceiver;
@ -89,7 +89,7 @@ public class StatsActivity extends BaseActivity {
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateVPNStats(intent);
updateStats(intent);
}
};
@ -109,8 +109,8 @@ public class StatsActivity extends BaseActivity {
.unregisterReceiver(mReceiver);
}
private void updateVPNStats(Intent intent) {
VPNStats stats = (VPNStats) intent.getSerializableExtra("value");
private void updateStats(Intent intent) {
CaptureStats stats = (CaptureStats) intent.getSerializableExtra("value");
mBytesSent.setText(Utils.formatBytes(stats.bytes_sent));
mBytesRcvd.setText(Utils.formatBytes(stats.bytes_rcvd));

View File

@ -59,7 +59,7 @@ import com.emanuelef.remote_capture.Utils;
import com.emanuelef.remote_capture.activities.MainActivity;
import com.emanuelef.remote_capture.interfaces.AppStateListener;
import com.emanuelef.remote_capture.model.Prefs;
import com.emanuelef.remote_capture.model.VPNStats;
import com.emanuelef.remote_capture.model.CaptureStats;
import com.emanuelef.remote_capture.views.AppsListView;
import com.emanuelef.remote_capture.views.PrefSpinner;
import com.pcapdroid.mitm.MitmAPI;
@ -269,7 +269,7 @@ public class StatusFragment extends Fragment implements AppStateListener, AppsLo
}
private void processStatsUpdateIntent(Intent intent) {
VPNStats stats = (VPNStats) intent.getSerializableExtra("value");
CaptureStats stats = (CaptureStats) intent.getSerializableExtra("value");
Log.d("MainReceiver", "Got StatsUpdate: bytes_sent=" + stats.pkts_sent + ", bytes_rcvd=" +
stats.bytes_rcvd + ", pkts_sent=" + stats.pkts_sent + ", pkts_rcvd=" + stats.pkts_rcvd);

View File

@ -21,10 +21,11 @@ package com.emanuelef.remote_capture.model;
import java.io.Serializable;
public class VPNStats implements Serializable {
public class CaptureStats implements Serializable {
public String alloc_summary;
public long bytes_sent;
public long bytes_rcvd;
public long pcap_dump_size;
public int pkts_sent;
public int pkts_rcvd;
public int pkts_dropped;
@ -37,12 +38,14 @@ public class VPNStats implements Serializable {
/* Invoked by native code */
public void setData(String _alloc_summary,
long _bytes_sent, long _bytes_rcvd, int _pkts_sent, int _pkts_rcvd,
long _bytes_sent, long _bytes_rcvd, long _pcap_dump_size,
int _pkts_sent, int _pkts_rcvd,
int _pkts_dropped, int _num_dropped_conns, int _num_open_sockets,
int _max_fd, int _active_conns, int _tot_conns, int _num_dns_queries) {
alloc_summary = _alloc_summary;
bytes_sent = _bytes_sent;
bytes_rcvd = _bytes_rcvd;
pcap_dump_size = _pcap_dump_size;
pkts_sent = _pkts_sent;
pkts_rcvd = _pkts_rcvd;
pkts_dropped = _pkts_dropped;

View File

@ -187,7 +187,7 @@ static int get_uid_q(uid_resolver_t *resolver,
// Resolve method
jclass vpn_service_cls = (*env)->GetObjectClass(env, resolver->vpn_service);
resolver->getUidQ = jniGetMethodID(env, vpn_service_cls, "getUidQ",
"(IILjava/lang/String;ILjava/lang/String;I)I");
"(ILjava/lang/String;ILjava/lang/String;I)I");
if(!resolver->getUidQ)
return UID_UNKNOWN;
@ -205,7 +205,7 @@ static int get_uid_q(uid_resolver_t *resolver,
if((jsource != NULL) && (jdest != NULL)) {
juid = (*env)->CallIntMethod(
env, resolver->vpn_service, resolver->getUidQ,
version, conn_info->ipproto, jsource, sport, jdest, dport);
conn_info->ipproto, jsource, sport, jdest, dport);
jniCheckException(env);
}

View File

@ -72,13 +72,13 @@ static void sendStatsDump(pcapdroid_t *pd) {
jobject stats_obj = (*env)->NewObject(env, cls.stats, mids.statsInit);
if((stats_obj == NULL) || jniCheckException(env)) {
log_e("NewObject(VPNStats) failed");
log_e("NewObject(CaptureStats) failed");
return;
}
(*env)->CallVoidMethod(env, stats_obj, mids.statsSetData,
allocs_summary,
capstats->sent_bytes, capstats->rcvd_bytes,
capstats->sent_bytes, capstats->rcvd_bytes, pd->pcap_dump.tot_size,
capstats->sent_pkts, capstats->rcvd_pkts,
min(pd->num_dropped_pkts, INT_MAX), pd->num_dropped_connections,
stats->num_open_sockets, stats->all_max_fd, active_conns, tot_conns,
@ -490,7 +490,7 @@ Java_com_emanuelef_remote_1capture_CaptureService_runPacketLoop(JNIEnv *env, jcl
cls.vpn_service = vpn_class;
cls.conn = jniFindClass(env, "com/emanuelef/remote_capture/model/ConnectionDescriptor");
cls.conn_update = jniFindClass(env, "com/emanuelef/remote_capture/model/ConnectionUpdate");
cls.stats = jniFindClass(env, "com/emanuelef/remote_capture/model/VPNStats");
cls.stats = jniFindClass(env, "com/emanuelef/remote_capture/model/CaptureStats");
cls.blacklist_status = jniFindClass(env, "com/emanuelef/remote_capture/Blacklists$NativeBlacklistStatus");
cls.blacklist_descriptor = jniFindClass(env, "com/emanuelef/remote_capture/model/BlacklistDescriptor");
cls.matchlist_descriptor = jniFindClass(env, "com/emanuelef/remote_capture/model/MatchList$ListDescriptor");
@ -505,7 +505,7 @@ Java_com_emanuelef_remote_1capture_CaptureService_runPacketLoop(JNIEnv *env, jcl
mids.dumpPcapData = jniGetMethodID(env, vpn_class, "dumpPcapData", "([B)V");
mids.stopPcapDump = jniGetMethodID(env, vpn_class, "stopPcapDump", "()V");
mids.updateConnections = jniGetMethodID(env, vpn_class, "updateConnections", "([Lcom/emanuelef/remote_capture/model/ConnectionDescriptor;[Lcom/emanuelef/remote_capture/model/ConnectionUpdate;)V");
mids.sendStatsDump = jniGetMethodID(env, vpn_class, "sendStatsDump", "(Lcom/emanuelef/remote_capture/model/VPNStats;)V");
mids.sendStatsDump = jniGetMethodID(env, vpn_class, "sendStatsDump", "(Lcom/emanuelef/remote_capture/model/CaptureStats;)V");
mids.sendServiceStatus = jniGetMethodID(env, vpn_class, "sendServiceStatus", "(Ljava/lang/String;)V");
mids.getLibprogPath = jniGetMethodID(env, vpn_class, "getLibprogPath", "(Ljava/lang/String;)Ljava/lang/String;");
mids.notifyBlacklistsLoaded = jniGetMethodID(env, vpn_class, "notifyBlacklistsLoaded", "([Lcom/emanuelef/remote_capture/Blacklists$NativeBlacklistStatus;)V");
@ -517,7 +517,7 @@ Java_com_emanuelef_remote_1capture_CaptureService_runPacketLoop(JNIEnv *env, jcl
mids.connUpdateSetInfo = jniGetMethodID(env, cls.conn_update, "setInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V");
mids.connUpdateSetPayload = jniGetMethodID(env, cls.conn_update, "setPayload", "(Ljava/util/ArrayList;Z)V");
mids.statsInit = jniGetMethodID(env, cls.stats, "<init>", "()V");
mids.statsSetData = jniGetMethodID(env, cls.stats, "setData", "(Ljava/lang/String;JJIIIIIIIII)V");
mids.statsSetData = jniGetMethodID(env, cls.stats, "setData", "(Ljava/lang/String;JJJIIIIIIIII)V");
mids.blacklistStatusInit = jniGetMethodID(env, cls.blacklist_status, "<init>", "(Ljava/lang/String;I)V");
mids.listSize = jniGetMethodID(env, cls.list, "size", "()I");
mids.listGet = jniGetMethodID(env, cls.list, "get", "(I)Ljava/lang/Object;");

View File

@ -1191,6 +1191,8 @@ int pd_run(pcapdroid_t *pd) {
log_d("Stopped packet loop");
// send last dump
if(pd->cb.send_stats_dump)
pd->cb.send_stats_dump(pd);
if(pd->cb.send_connections_dump)
pd->cb.send_connections_dump(pd);